复杂的正则表达式 sed 替换不起作用但不抛出错误

复杂的正则表达式 sed 替换不起作用但不抛出错误

我正在 CentOS 7 中工作,尝试使用 find / sed oneliners 来修复大量文件。具体来说是连续两个:

  1. [monitor://...]首先,在每个(工作)之后立即添加“ignoreOlderThan = 14d”
  2. 其次,找到一个[monitor://...]具有两个“ignoreOlderThan”的组并删除最后一个出现的情况。

我有数百个与此类似的文件(这是我正在使用的当前测试文件):

[default]
host = 10.2.2.15

[monitor://apath]
ignoreOlderThan = 14d
index=test
sourcetype=whatever
ignoreOlderThan = 30d

[monitor://truck]
ignoreOlderThan = 14d

[monitor://apath]
ignoreOlderThan = 14d
index=test
sourcetype=whatever
ignoreOlderThan = 30d

我使用的第一个完整命令是:

find -name inputs.conf -exec sed -ie 's/\(\[monitor:.*\]\)/\1\nignoreOlderThan = 14d/g' {} +

这个有效。它ignoreOlderThan = 14d紧接着添加在[monitor://...].

第二个更复杂,不起作用:

find -name inputs.conf -exec sed -ie 's/\(\[monitor[^\]]+\][^\[]?\)\(ignoreOlderThan\s?=\s?[0-9]+\w\)\([^\[]+?ignoreOlderThan\s?=\s?[0-9]+\w\)\([^\[]+\)?/\1\3\4/g' {} +

我使用 regex101 测试了几种可能的场景:

https://regex101.com/r/okCSfl/6

https://regex101.com/r/okCSfl/7

https://regex101.com/r/okCSfl/8

https://regex101.com/r/okCSfl/9

正则表达式有效,所以我认为问题出在 sed 命令中的某个地方,而我的能力要弱得多。我已经根据捕获组的需要转义了括号,并且命令运行......但它没有执行任何操作。我认为这可能是因为有时第四个捕获组不存在,但我还测试了一个文件,其中每个组都包含所有 4 个捕获组。

我还读到一些 sed 将所有内容解释为一行,这就是为什么我的一些测试用例在换行符之间根本没有空格。


编辑:@choroba 指出 sed 一次执行一行并建议 perl 并给出了一个例子。我玩了一下并让它与以下内容一起工作:

find -name inputs.conf -exec perl -0777 -pi -e 's/(\[monitor:[^[]+?)^(ignoreOlderThan\s?=\s?[0-9]+\w)([^[]+?^ignoreOlderThan\s?=\s?[0-9]+\w[^[]+)/$1$3/gms' {} +

此处演示:

https://regex101.com/r/okCSfl/10

答案1

sed 逐行处理输入。它的正则表达式不能轻易匹配多行。

另一方面,当-0777指定选项时,Perl 可以读取整个文件:

perl -0777 -pe 's/^(\[monitor:[^[]+^ignoreOlderThan .*)^ignoreOlderThan = \w+/$1/gms' input > output
  • -0777吞掉整个文件
  • -p处理后打印输入
  • /g重复替换
  • /s匹配.换行符(通常不会)
  • /m^在每个换行符的开头进行匹配,而不仅仅是整个字符串(类似地$,但我们在这里不需要它)

相关内容