0

i wanted to capture \n in a variable (assume a) and substitute $a in front of search pattern in a file (abc.txt)

can somebody suggest me the solution ?

> cat abc.txt
hi how are you how is your health
> echo $a
\

expected output ( search pattern - how)

hi \
how are you \
how is your health
  • a=$(printf "\n") ? – Raman Sailopal Nov 21 '17 at 13:47
  • @RamanSailopal, that wouldn't work as command substitution strips trailing newline characters. – Stéphane Chazelas Nov 21 '17 at 13:51
  • What does "in front of a search pattern in a file" mean? – B Layer Nov 21 '17 at 13:54
1

In a Bourne-like or rc-like shell

a='
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt

would pass a a environment variable to perl containing a newline character and perl would insert the content of that variable before each occurrence of pattern in the content of abc.txt.

To assign any character x other than ' to a variable in Bourne-like shells, you can use:

a='x'

So for backslash:

a='\'

For newline:

a='
'

For control characters like newline, but that would be even worse for backspace or carriage-return for instance, however, that renders the code less legible.

ksh93 introduced a new $'...' form of quotes to specify those characters in an escaped form. Other shells like bash, zsh, mksh or FreeBSD sh have copied and extended (like the $'\uXXXX' form added by zsh) it since.

In those shells, you can use:

a=$'\n' a=$'\b' a=$'\r' a=$'\\' a=$'\''

To assign a newline, backspace, carriage return, backslash or single quote character.

That quoting operator is not standard yet, so you can't use it in a portable sh script. A standard alternative is to use:

a=$(printf '\b')

for backspace for instance, but that doesn't work for newline as command substitution ($(cmd)) strips trailing newline characters from the output of cmd. One has to resort to hacks like:

nl=$(printf '\n.'); nl=${nl%.}

(that is add a . and remove it afterwards) in order to preserve it.

Note that perl also understands those \n notations in its code, so you can do:

perl -pe 's/pattern/\n$&/g' < abc.txt

The GNU implementation of sed (and a few others nowadays) also support it:

sed 's/pattern/\n&/g' < abc.txt

but that's not standard. Standardly, a newline in the replacement part of the s command in sed has to be expressed with a backslash followed by an actually newline, so that would be:

backslash='\' newline='
'
sed "s/pattern/$backslash$newline&/g" < abc.txt

Or without the variables:

sed 's/pattern/\
&/g' < abc.txt

So, if you want to insert both a backslash and a newline in front of pattern, you need:

sed 's/pattern/\\\
&/g' < abc.txt

3 backslashes in total, two for a literal backslash and one for the newline. Or with perl:

perl -pe 's/pattern/\\\n$&/g' < abc.txt

Or with your a variable:

a='\
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt
  • ======= > echo $a \ > a=' ' perl -pe 's/how/$ENV{a}$&/g' < abc.txt hi how are you =========== @StéphaneChazelas .. this is not printing \ (backslash) – Vikas Venna Nov 21 '17 at 14:42
  • @Vika, see edit. I see that you've now clarified your question. – Stéphane Chazelas Nov 21 '17 at 14:45
  • it worked .. thank you ============== > sed 's/how/\\\ > &/g' < abc.txt hi \ how are you \ how is your health ============ when I use sed -i (to edit the same file ) it is complaining "sed: no input files". can you help me here ? – Vikas Venna Nov 21 '17 at 15:06
0

You can also use the own bash commands using:

cat abc.txt | sed -e 's/how/\nhow/g' |  while read line; do echo "$line \\"; done
  • this is printing \ at the end of all lines. – Vikas Venna Nov 22 '17 at 9:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.