在字符串a之后替换字符串b的第一次出现

时间:2019-08-01 10:34:31

标签: bash sed command-line

我想在多个文件(cpp代码)中搜索某个字符串A,并用字符串C替换下一次出现的字符串B。

**示例:

traceDebug( "text" ) );

结果应为:

traceDebug( "text" );



String A = "traceDebug"

String B = ") );"

String C = ");"

因此,第一个occurence of ") );应该替换为);

我不能简单地删除),因为如果我愿意的话,文件中会存在语法错误的星座。

3 个答案:

答案 0 :(得分:0)

像这样吗?

$ cat foo.txt
traceDebug ( "text" ) );
ignoreMe ( "text" ) );
traceDebug
( "text" ) );
) );
$ sed '/traceDebug/s/) );/);/;t;/traceDebug/,/) );/s/) );/);/' foo.txt
traceDebug ( "text" );
ignoreMe ( "text" ) );
traceDebug
( "text" );
) );

t是一个条件分支,如果单行替换更改了该行,它将忽略范围替换。就个人而言,如果需要使用分支,我会开始考虑使用sed以外的工具!

答案 1 :(得分:0)

您可以使用Perl一线式实现:

perl -i.bak -pE 'BEGIN { undef $/; } s/traceDebug.+?\K\) \);/\);/gs' whatever_files*.cpp

编辑要在bash的子目录中的文件上运行此操作,最简单的方法可能是:

( shopt -s globstar ; perl -i.bak -pE 'BEGIN { undef $/; } s/traceDebug.+?\K\) \);/\);/gs' **/*.cpp )

示例输入:

traceDebug ( "text" ) );
traceDebug
( "text" ) );
) );

do_not_replace (3 * ( 4 + 5 ) );

示例输出:

traceDebug ( "text" );
traceDebug
( "text" );
) );

do_not_replace (3 * ( 4 + 5 ) );

说明:

  • -i.bak:就地编辑;原始文件另存为foo.cpp.bak
  • BEGIN { undef $/; }:不要换行,而是立即读取整个文件
  • s/traceDebug.+?\K\) \);/\);/gs:进行替换。
    • traceDebug.+?:在.+?之后尽可能少地{traceDebug
    • \K:将这一部分排除在即将到来的替换项之外
    • \) \);:我们要更改的内容(在\K之后)
    • \);:替代人
    • /gs:替换所有匹配项( G 小数点),并允许.匹配换行符,就好像整个字符串是 S 英格线

s///gs运行之后,Perl自己负责将输入文件重命名为.bak,并将输出保存在原始文件名下。

答案 2 :(得分:0)

这可能对您有用(GNU sed):

sed '/traceDebug/{:a;s/) );/);/;t;n;ba}' file

将处理范围缩小到包含traceDebug的行。此后,将) );替换为);并纾困。否则,打印当前行,获取下一行并重复直到成功。

相关问题