[英]Find multi-line text & replace it, using regex, in shell script
我试图找到两个连续行的模式,其中第一行是固定字符串,第二行有一部分 substring 我喜欢替换。
这将在 macOS 上的sh
或bash
中完成。
如果我手头有一个可以对整个文本进行操作的正则表达式工具,这对我来说很容易。 但是,我发现的只是 bash 的简单文本替换——它不适用于正则表达式,以及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”。
作为一个忽略行分隔符的正则表达式,我会这样写:
(\bkeyB\n\s*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
。 {...}
创建一个仅在满足/keyB$/
条件时才执行的块。
请参阅在线sed
演示。
使用带有-0777
的 perl 单线扫描多行:
$ # inline edit:
$ perl -0777 -i -pe 's/\bkeyB\s*value):\d*/$1:888/' file.txt
$ # to stdout:
$ cat file.txt | perl -0777 -pe 's/\bkeyB\s*value):\d*/$1:888/'
在普通 bash 中:
#!/bin/bash
keypattern='^[[:blank:]]*keyB$'
valpattern='(.*):'
replacement=888
while read -r; do
printf '%s\n' "$REPLY"
if [[ $REPLY =~ $keypattern ]]; then
read -r
if [[ $REPLY =~ $valpattern ]]; then
printf '%s%s\n' "${BASH_REMATCH[0]}" "$replacement"
else
printf '%s\n' "$REPLY"
fi
fi
done < file
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.