1

I have a file ".gitignore" contains various source file name as

src/abc
src/line
src/another

I like to add another line "src/line.cpp" after a match found "src/line" result would look like as

src/abc
src/line
src/line.cpp
src/another

I am using sed as

set -- "$File"   // $File contains src/line
IFS="/"; declare -a Array=($*)
echo "${Array[0]}"   // This prints src
echo "${Array[1]}"   // This prints line

sed -i '/$Array[0]\/$Array[1]/a $Array[0]\/$Array[1].cpp'  $File

The sed command is not working. I have a feeling that slashes are not properly handled. If I hard code as

sed -i '/src\/line/a src\/line.cpp' $File

then it works. Any solutions? Thanks in advance!

  • 1
    @fedorqui: This is not a duplicate of that; the OP's working line matches your suggested duplicate. Rather, the OP's problem is the use single quotes `'` rather than double `"`. – Joseph Quinsey Mar 03 '14 at 15:20

3 Answers3

2

You properly use double-quotes in echo "${Array[1]}", and the braces {} needed for the array index. But you neglect to do so in your sed line. So try:

sed -i "/${Array[0]}\/${Array[1]} *$/a ${Array[0]}\/${Array[1]}.cpp" .gitignore

I've added an extra $ here for the end of the line, so:

  • Repeating the command leaves the file unchanged
  • Reduces risk of inadvertent matches

The space-star-dollar *$ handles the case where a line has blank spaces at the end. You may also want to add a ^ to match the start of line.

Also, your sed command operates on $File; I think you want .gitignore.

But rather than fiddle around with IFS and arrays, it might be cleaner to use bash's parameter substitution. Replace ${Array[0]} and ${Array[1]} with:

  ${File%/*}
  ${File#*/}

Finally, you don't even need to do that, if you replace the sed slash / with for example @ (but underscore _ would be bad, as it is commonly used in filenames).

So the penultimate command line is:

sed -i "\@$File@a $File.cpp" .gitignore

or, to handle blanks at the end of a line and to avoid spurious matches:

sed -i "\@$File *\$@a $File.cpp" .gitignore

Note only the first @ is escaped.

Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
1

With GNU sed, you can do it like:

sed -i.BAK 's_src/line_\0\n\0.txt_'

As it allows to use other separators than slashes.

Zsolt Botykai
  • 50,406
  • 14
  • 85
  • 110
0

You can use it this way:

s='src/line'; r='src/line.cpp'; sed "s~$s~&\n$r~" file
src/abc
src/line
src/line.cpp
src/another
anubhava
  • 761,203
  • 64
  • 569
  • 643