在 bash 脚本中使用 sed 替换多行模式
Posted
技术标签:
【中文标题】在 bash 脚本中使用 sed 替换多行模式【英文标题】:Multiline pattern replacement with sed in bash script 【发布时间】:2021-09-12 05:01:37 【问题描述】:尝试用两个字符,
替换多行
如果可以搜索到下面的内容并用上面的替换,那么问题就解决了。
模式遇到时是这样的:
,
]
"query":
"bool":
"minimum_should_match": 1,
"should": [
这些是我目前尝试过的方法
#using \ and spaces
combinedDSL=$(echo "$initialDSLs"|sed 's/\
]\
\
\
\
\
*\
\
"query": \
"bool": \
"minimum_should_match": 1,\
"should": [\
/,/' )
echo "$combinedDSL"
#using line breaks \n
combinedDSL2=$(echo "$initialDSLs|"sed N 's/\n]\n\n\n\n\n*\n\n"query": \n"bool": \n"minimum_should_match": 1,\n"should": [\n/,/')
echo "$combinedDSL2"
这里是完整的上下文:
"query":
"bool":
"minimum_should_match": 1,
"should": [
"wildcard":
"author_place": "*city*"
,
"wildcard":
"meta.title.results": "*state*"
,
]
"query":
"bool":
"minimum_should_match": 1,
"should": [
"wildcard":
"author": "*cat*"
,
"wildcard":
"meta.hashtag.results": "*Monkey*"
]
【问题讨论】:
edit 你的问题是在上下文中显示目标行,这些行被你不想匹配的行包围,并在给定输入的情况下添加预期的输出。 这看起来像 JSON,这意味着您需要使用像jq
这样的 JSON 感知工具来处理它。
我已将上下文添加到问题中。 @埃德莫顿
您提供的“上下文”中没有任何部分与您要替换的字符串匹配。每一行之间有不同数量的空白行,一个逗号在另一个中不存在,并且缺少换行符和不同的缩进。请清理您的示例,以便您要查找的字符串存在于您的示例输入中。
通过大量工作,您可能可以创建一个复杂的正则表达式,为您的特定 JSON 文件完成这项工作。但在我看来,这是该项目的错误工具。最好学习如何使用现有的许多 JSON 工具,并且下次更加灵活。
【参考方案1】:
$ cat tst.sh
#!/usr/bin/env bash
old=' ,
]
"query":
"bool":
"minimum_should_match": 1,
"should": [
'
new='
,'
# https://***.com/questions/29613304/is-it-possible-to-escape-regex-metacharacters-reliably-with-sed
# explains how in the script below we turn "old" above into a robust
# regexp that's forgiving of white space differences in the target file
# and deactivate the possible backreference in "new".
old="$old" new="$new" awk '
BEGIN
old = ENVIRON["old"]
new = ENVIRON["new"]
# Deactivate possible regexp metachars in "old"
gsub(/[^^\\[:space:]]/,"[&]",old) # deactivate all non-space chars except ^ and \
gsub(/\^/,"\\^",old) # deactivate ^
gsub(/\\/,"\\\\",old) # deactivate \
# Make any literal white space present in "old" match all white space
gsub(/[[:space:]]+/,"[[:space:]]+",old)
# Deactivate possible backreference metachars in "new"
gsub(/&/,"\\&",new) # deactivate &
# Create a single input record out of the whole input file
rec = (NR>1 ? rec RS : "") $0
END
gsub(old,new,rec)
print rec
' "$@:--"
$ ./tst.sh file
"query":
"bool":
"minimum_should_match": 1,
"should": [
"wildcard":
"author_place": "*city*"
,
"wildcard":
"meta.title.results": "*state*"
,
"wildcard":
"author": "*cat*"
,
"wildcard":
"meta.hashtag.results": "*Monkey*"
]
【讨论】:
以上是关于在 bash 脚本中使用 sed 替换多行模式的主要内容,如果未能解决你的问题,请参考以下文章