bash shell在找到模式匹配后在文件中添加新行

时间:2014-03-03 14:46:49

标签: bash sed

我有一个文件“ .gitignore ”包含各种源文件名

src/abc
src/line
src/another

我想在找到“ src / line ”匹配后添加另一行“ src / line.cpp ” 结果看起来像

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

我使用sed作为

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

sed命令无效。 我有一种感觉,斜线没有得到妥善处理。如果我硬编码为

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

然后它的工作原理。 有解决方案吗提前谢谢!

3 个答案:

答案 0 :(得分:2)

您正确使用echo "${Array[1]}"中的双引号,以及数组索引所需的大括号{}。但你忽略了在sed行中这样做。所以试试:

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

我在这里添加了一个额外的$作为行尾,所以:

  • 重复命令会使文件保持不变
  • 降低无意匹配的风险

space-star-dollar *$处理行末尾有空格的情况。您可能还想添加^以匹配行首。

此外,您的sed命令在$File上运行;我想你想要.gitignore

但是,使用bash的参数替换可能更清晰,而不是摆弄IFS和数组。将${Array[0]}${Array[1]}替换为:

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

最后,如果用例如/替换sed斜杠@,你根本不需要这样做(但是下划线_会很糟糕,因为它通常是用于文件名)。

所以倒数第二个命令行是:

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

或者,在一行的末尾处理空白并避免虚假匹配:

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

请注意,只有第一个@已转义。

答案 1 :(得分:1)

使用GNU sed,您可以这样做:

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

因为它允许使用除斜线之外的其他分隔符。

答案 2 :(得分:0)

你可以这样使用它:

s='src/line'; r='src/line.cpp'; sed "s~$s~&\n$r~" file
src/abc
src/line
src/line.cpp
src/another