Reputation: 31
I'm trying with GNU sed
command to append a line into a file inside a block/section, specifically just a line under the start of the block/section. As a result it empties the file (maybe leaves a linebreak) and then appends the line in question.
The MAGIC_STRING
variable contains the string delimiting the block contents at both ends.
Here's an example script:
MAGIC_STRING='#!#%%%===!!'
DNS_REGISTRY='\ntomato IN A 222.88.1.2\n'
file=/home/anyuser/file.txt #file exists and has initial content
appended_string=$(sed -n -i "0,/^$MAGIC_STRING/!b; //a $DNS_REGISTRY" $file)
echo "APPENDED: $appended_string"
[[ -n "$appended_string" ]] && echo "Modified file"
The example file's initial contents:
#!#%%%===!!
tomato IN A 222.88.1.2
#!#%%%===!!
I tried escaping MAGIC_STRING
characters and putting "\" at the start of "a" command.
I expected it to match a single MAGIC_STRING
and then just append the line below the start of the block if any and ignore all other lines. And, above all to keep file's contents intact.
Also, I expected sed to output to stdout the pattern space after modification, which I tested before... but in this case it simply doesn't for some reason.
Please, don't recommend me awk
as an alternative...
Upvotes: 0
Views: 84
Reputation: 31
Thanks to @Barmar I checked at the -n and -i options once again and reached to the conclusion on why the target file was empty except for the appended text. The -i
option redirects sed's pattern space output to the file in a direct fashion without exceptions basically, plus -n
which suppresses its automatic output.
This solution consists of writing the last line of the file (it could be anything as signal) to standard output after the text is appended to the file as well as excluding the -n
option. Executing sed
with sudo
(if not root) is also necessary because sed requires root permissions for w
(writing) to /dev/stdout.
appended_string=$(sudo -S <<< "$PASSWORD" sed -i -e "0,/^$MAGIC_STRING/!b; //!b ; //a $DNS_REGISTRY" -e '$w /dev/stdout' $file)
Both -e
options are necessary because the a
command escapes all subsequent characters in the script thus making impossible to write further commands, so separating the main script into 2 solves this.
On the other hand, there is another more reliable, neater approach to ensure whether a file was changed by sed or not, which consists of saving to a variable the old file's version, executing sed and then comparing the current file's contents with those of the variable using diff
command:
local old_file="$(cat $file)"
sudo -S <<< "$PASSWORD" sed -i -e "0,/^$MAGIC_STRING/!b; //a $DNS_REGISTRY" $file
if diff <(echo -n "$old_file") $file; then
echo Failed to add registry to \"$file\"
else
echo 'Success!';
fi
echo -n
spares the newline at the end of the output and the <()
wrapping around it makes possible to refer to the variable's as a file.
Upvotes: 1