【发布时间】:2018-01-09 05:28:07
【问题描述】:
有很多不同的单行字符串替换解决方案,但我很好奇什么最有效的方法是只使用 bash 内置函数来执行多行替换。
我正在使用以下解决方案,使用 bash 的内置正则表达式,如果只有一个匹配项,它可以正常工作:
read -r -d '' to_search <<'EOF'
1
2
3
-
1
2
3
-
1
2
3
EOF
read -r -d '' to_find <<'EOF'
1
2
3
EOF
read -r -d '' to_replace <<'EOF'
a
b
c
EOF
[[ $to_search =~ (.*)($to_find)(.*) ]] &&
echo "${BASH_REMATCH[1]}$to_replace${BASH_REMATCH[3]}"
如果我想替换所有匹配项,这也可以工作,因为我可以循环直到没有匹配项。但它没有提供非贪婪的解决方案,因为 bash 的内置正则表达式不支持 ? 运算符。
例如,因为匹配是贪心的,所以输出只会考虑最后一个匹配,而不是在第一个匹配。例如:
1
2
3
-
1
2
3
-
a
b
c
一种解决方案可能是将输入和匹配字符串拆分为数组,然后在循环中逐步遍历它们以找到匹配项,但这可能不是最佳的。
我欢迎其他解决方案供参考,但具体问题是仅使用 bash 内置函数来解决此问题。这可以通过将字符串传递给 Python 或 Perl 来解决,但这不是我想要的。
欢迎使用常用工具 (sed/grep/awk) 的替代方案的答案作为参考和比较,但不会被接受,因为它没有回答这个特定问题。适用于不提供正则表达式工具的旧 bash 环境的解决方案的额外加分。
请注意,这对于 sed 和 grep 来说一开始可能看起来很容易,但是这两个工具都只在单个行上执行匹配,不适合多行匹配。
【问题讨论】:
-
错了!
sed确实能够处理多行匹配,尽管您不会经常看到这样的用法。请参阅带有大写字母here 的sed命令。