如何检查sed脚本中的上一行?

时间:2018-10-18 14:16:56

标签: bash sed

我需要在某些C ++代码中禁止显示许多MSVC警告。

之前:

//...
#include <atomic>
//...

之后:

//...
#pragma warning(push)
#pragma warning(disable : 4995)
#include <atomic>
#pragma warning(pop)
//...

我正在为此目的使用sed:

sed -b -r -i "s;(\s*#include <atomic>.*);#pragma warning(push)\n#pragma warning(disable : 4995)\n\1\n#pragma warning(pop);" macarena.h

只需将1行替换为3。但是我想多次运行此脚本。如何检查上一行是否与#pragma warning(disable : 4995)匹配,并忽略当前行呢?

3 个答案:

答案 0 :(得分:1)

抢救Perl!

perl -0777 -pe '$disable = "#pragma warning(disable : 4995)\n";
                $push    = "#pragma warning(push)\n";
                $pop     = "#pragma warning(pop)";
                s/(?<!\Q$disable\E)(#include <atomic>)/$push$disable$1\n$pop/g
               ' -- file
  • -0777设置“悬浮模式”,即它将整个文件读入内存并进行处理
  • -p在处理后打印每个块
  • (?<!...)是断言背后的否定之眼,它表示“不以”开头,即只有在不以disable pragma开头的情况下,替换才会替换include。

我发现它比sed解决方案更具可读性

sed $'/^#pragma warning(disable : 4995)/{n;n}
      /^#include <atomic>/{i#pragma warning(push)\\\n#pragma warning(disable : 4995)\n;
                           a#pragma warning(pop)\n}' file

在遇到禁用条件时跳过下面的检查。

答案 1 :(得分:1)

您可以使用此awk

awk -v p='#pragma warning(disable : 4995)' '
index($0, "#include <atomic>") && prev != p {
      $0 = sprintf("#pragma warning(push)\n%s\n%s\n#pragma warning(pop)", p, $0)
}
{ prev=$0 } 1' file

答案 2 :(得分:0)

由于行#include <atomic>位于pragma warning(disable : 4995)pragma warning(pop)之间,我们可以排除ranges

sed -b -r -i '/#pragma warning\(disable : 4995\)/,/#pragma warning\(pop\)/ !{
    s;(\s*#include <atomic>.*);#pragma warning(push)\n#pragma warning(disable : 4995)\n\1\n#pragma warning(pop);
}' macarena.h