While appending some text after a matched pattern, I wanted to add an empty line with a comment to isolate my additions from the rest. However, I have noticed that for the very first n, I need to escape the with an additional (makes it \n) but this is apparently not required for rest of the appended text. Why is this so?
An example that I produced on a SUSE 11 server (bash v3.2.57(2) and GNU sed version 4.1.5) is:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="096c6d7e6d6c7f49616d796c6d6e6c38">[email protected]</a>:/edw> sed '/test/a \nNot a testnJust Playing' <<< test test Not a test Just Playing
If I do not escape the first n (right after the a sed command, I get an n printed instead of a newline.
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9efbfae9fafbe8def6faeefbfaf9fbaf">[email protected]</a>:/edw> sed '/test/a nNot a testnJust Playing' <<< test test nNot a test Just Playing
Notice that I have intentionally added a space after a command so that it doesn’t conflict accidentally with alternate syntax.
Same behavior is observed if I replace n with t.Number of spaces after a command do not seem to matter; the first backslash needs to be escaped to print the special character even after multiple spaces.
Same is the case on another environment, where I originally observed this; a Centos 7 x64 VM, bash version is 4.2.46(2) and sed version is GNU sed 4.2.2
sed -i '/[mysqld]/a \n# <<INSERTED MANUALLY>>ntransaction-isolation=READ-COMMITTEDninnodb_flush_method=O_DIRECTnmax_connections=550n# <<END OF MANUAL INSERTIONS >>n' /etc/my.cnf
Output:
... [mysqld] # <<INSERTED MANUALLY>> transaction-isolation=READ-COMMITTED innodb_flush_method=O_DIRECT max_connections=550 # <<END OF MANUAL INSERTIONS >> ...
Output Without Escaping first n:
[mysqld] n# <<INSERTED MANUALLY>> transaction-isolation=READ-COMMITTED innodb_flush_method=O_DIRECT max_connections=550 # <<END OF MANUAL INSERTIONS >>
Is there any particular reason for this behavior? I am unable to find any details while skimming through the docs (here), through, admittedly, I haven’t read the entire documentation thoroughly.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The standard form of the a command in sed is
a text to be appended
The c and i command follow the same format.
If further lines are to be appended, the newline of each has to be escaped:
a text to be appended
Standard sed does not know to interpret n as newline as GNU sed does, so your single line command with a non-GNU sed would be written (in bash) as
sed $'/test/a\n\nNot a test\nJust Playingn' <<<test
Here, we use $'...' to make the shell replace each n with an actual newline and \ with .
The command could be written as the following without the $'...' feature of bash:
sed '/test/a Not a test Just Playing ' <<<test
Both of these commands would work with GNU sed too.
GNU sed additionally allows the appended text to occur without an intervening newline between it and the preceding a, and allows for dropping the completely, but will interpret the immediately following the a command as the backslash in the standard a form of the command (this is the basic issue in your question). GNU sed also adds a newline at the end of the appended text in the script. So with GNU sed, you could write
sed '/test/a Not a test Just Playing' <<<test
or, using the fact that GNU sed knows n,
sed '/test/a\nNot a testnJust Playing' <<<test
Method 2
It’s not exactly documented behaviour, but then the entire thing is an extension. All three commands that were extended similarly (a, i and c) behave the same way: leading whitespace is ignored, and if the text begins with , then it is discarded. Essentially, it doesn’t matter to sed which of these forms are used:
i foo i foo i foo
They’re all identical. (I know I used i here, but check the the descriptions of a, i and c – it’s surreal.)
And the code shows as much:
1111 case 'a': 1112 case 'i': 1113 case 'c': 1114 ch = in_nonblank (); 1115 1116 read_text_to_slash: 1117 if (ch == EOF) 1118 bad_prog (_(EXPECTED_SLASH)); 1119 1120 if (ch == '\') 1121 ch = inchar ();
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0