在shell脚本中使用正则表达式查找多行文本并替换它



我试图找到两个连续行的模式,其中第一行是固定字符串,第二行有我喜欢替换的部分子字符串。

这是在macOS的shbash中完成的。

如果我手头有一个可以对整个文本进行操作的正则表达式工具,这对我来说会很容易。然而,我所发现的只是bash的简单文本替换-它不能与regex和sed一起工作,这是面向行的。

我怀疑我可以以一种方式使用sed,它首先找到匹配的第一行,只有在它的模式也匹配的情况下才会替换下面的行,但我无法弄清楚。

或者macOS上是否有其他工具可以让我对整个文件或字符串进行基于正则表达式的搜索和替换?也许使用Python(安装了v2.7和v3)?

下面是一个示例文本,以及我对它的修改方式:

keyA
value:474
keyB
value:474    <-- only this shall be replaced (follows "keyB")
keyC
value:474
keyB
value:474

现在,我想找到所有第一行为"keyB"下面一行是"value:474",然后用另一个值替换第二行,例如"value:888"

作为一个忽略行分隔符的正则表达式,我会这样写:

  • Search:(bkeyBns*value):474
  • 替换:$1:888

所以,基本上,我找到了474之前的模式,然后用相同的模式加上新的数字888替换它,从而保留了原来的缩进(这是可变的)。

可以使用

sed -e '/keyB$/{n' -e 's/(.*):[0-9]*/1:888/' -e '}' file
# Or, to replace the contents of the file inline in FreeBSD sed:
sed -i '' -e '/keyB$/{n' -e 's/(.*):[0-9]*/1:888/' -e '}' file

细节:

  • /keyB$/-查找所有以keyB
  • 结尾的行
  • n-清空当前模式空间并读入下一行
  • s/(.*):[0-9]*/1:888/-找到任何文本直到最后一个:+零或更多的数字捕获文本到组1,并替换为组和:888的内容。

{...}创建一个block,该block只在满足/keyB$/条件时执行。

查看sed在线演示

使用带有-0777的perl一行代码扫描多行:

$ # inline edit:
$ perl -0777 -i -pe 's/bkeyBs*value):d*/$1:888/' file.txt
$ # to stdout:
$ cat file.txt | perl -0777 -pe 's/bkeyBs*value):d*/$1:888/'

bash:

#!/bin/bash
keypattern='^[[:blank:]]*keyB$'
valpattern='(.*):'
replacement=888
while read -r; do
printf '%sn' "$REPLY"
if [[ $REPLY =~ $keypattern ]]; then
read -r
if [[ $REPLY =~ $valpattern ]]; then
printf '%s%sn' "${BASH_REMATCH[0]}" "$replacement"
else
printf '%sn' "$REPLY"
fi
fi
done < file

相关内容

  • 没有找到相关文章

最新更新