1

We want to append with sed , the following complex line after matching the line that start with – number_of_cars_are

more /tmp/orig_file

number_of_cars_are=$number_of_cars_are

the line that we want to add:

numbers=` su hdfs -c "hdfs dfs -ls  $var/*.jar" |sed s'/\// /g' | awk '{print $NF}' | wc -m `

so we did the following

sed '/^[[:space:]]*number_of_cars_are =.*/a numbers=` su hdfs -c "hdfs dfs -ls  $var/*.jar" |sed s'/\// /g' | awk '{print $NF}' | wc -m `' /tmp/orig_file > /tmp/new_file

but we get the following

sed: can't read /g | awk {print: No such file or directory
sed: can't read } | wc -m `: No such file or directory

so we try also to add backslash as

sed '/^[[:space:]]*number_of_cars_are =.*/a numbers=` su hdfs -c \"hdfs dfs -ls  $var/*.jar\" |sed s'/\// /g' | awk '{print \$NF}' | wc -m `' /tmp/orig_file > /tmp/new_file

but the same

sed: can't read /g | awk {print: No such file or directory
sed: can't read $NF} | wc -m `: No such file or directory

any advice how to add the lines

3 Answers 3

2

Better to put the Sed commands in a file, so that the shell does not try to interpret the special symbols of the (wanna-be) appended line.

longline.sed:

/^[[:space:]]*number_of_cars_are=/a\
numbers=` su hdfs -c "hdfs dfs -ls  $var/*.jar" |sed s'/\\// /g' | awk '{print $NF}' | wc -m `

See that the only modification is to escape a backslash, because Sed interprets escaped characters.

$ sed -f longline.sed newfile
more /tmp/orig_file

number_of_cars_are=$number_of_cars_are
numbers=` su hdfs -c "hdfs dfs -ls  $var/*.jar" |sed s'/\// /g' | awk '{print $NF}' | wc -m `
0

We can use the heredoc << feature to good use in this scenario.

repl=$(cat - <<\eof |\
sed -e 's:[\&/]:\\&:g'
numbers=` su hdfs -c "hdfs dfs -ls  $var/*.jar" |sed s'/\// /g' | awk '{print $NF}' | wc -m `
eof
)
$ sed \
    -e '/^[[:blank:]]*number_of_cars_are=/G' \
    -e "s/\\n/&$repl/" \
 /tmp/orig_file 

As a first step, use the heredoc to print the line you want appended and process it to escape the RHS s/// characters and store it in the variable repl.

Then we plug it in the s/// rhs section on the selected line.

Note this method is eminently Posixly and doesn't require any files.It assumes uniline repl.

0

The main issue is that a single quoted string can't ever contain a single quote. To provide the inserted line on the command line, you would have to break out of the single quoted string, add a quoted single quote, and then continue the string. Each single quote would therefore be written as either '\'' or as '"'"', where the two flanking single quotes end and starts, respectively, the single quoted string before and after the single quote.

To avoid having to take too make extra precautions, you can instead provide the line that you want to insert as a text in a document.

Similar to Quasímodo's answer, but using a quoted here-document, possibly directly from the command line:

sed -f /dev/stdin file <<'END_SED'
/^number_of_cars_are/a\
numbers=` su hdfs -c "hdfs dfs -ls  $var/*.jar" |sed s'/\// /g' | awk '{print $NF}' | wc -m `
END_SED

Since the here-document is quoted (indicated by the single quotes around the initial END_SED delimiter), none of the expansion in it will be expanded by the shell.

The sed utility reads the here-document from its standard input using -f /dev/stdin.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .