Bash 将sed与可能有花括号的替换变量一起使用

Bash 将sed与可能有花括号的替换变量一起使用,bash,sed,Bash,Sed,我正在编写一个脚本,用于在目录中的一组文件上循环搜索一个文件srcFile中的字符串stringA,复制它后面的行stringToCopy,并将它粘贴到另一个文件outputFile中另一个搜索字符串stringB之后的行上。到目前为止,我拥有的复制/粘贴脚本如下 stringA="This is string A" stringB="This is string B" srcFile=srcFile.txt outpuFile=outputFile.txt replacement="/$str

我正在编写一个脚本,用于在目录中的一组文件上循环搜索一个文件srcFile中的字符串stringA,复制它后面的行stringToCopy,并将它粘贴到另一个文件outputFile中另一个搜索字符串stringB之后的行上。到目前为止,我拥有的复制/粘贴脚本如下

stringA="This is string A"
stringB="This is string B"
srcFile=srcFile.txt
outpuFile=outputFile.txt
replacement="/$stringA/{getline; print}"
stringToCopy="$(awk "$replacement" $srcFile)"
sed -i "/$stringB/!b;n;c${stringToCopy}" $outputFile
除了stringToCopy最终包含大括号外,脚本工作得非常好。例如

srcFile.txt:

This is string A
text to copy: {0}
outputFile.txt:

This is string B
line to be replaced
脚本完成后,我希望outputFile.txt

但塞德却被他的话噎住了

sed: -e expression #1, char 106: unknown command: `m'
我尝试过对有问题的字符串进行硬编码,并尝试了不同的变体,例如避开卷曲和引用字符串,但没有找到一个成功的组合,我对如何使其工作感到困惑

编辑 我有一个derp时刻,忘记了我的stringA也有花括号,这碰巧导致我的awk命令计算多行。这导致我的stringToCopy中出现了新行,这是我真正的问题,而不是花括号。所以真正的问题是,如何让awk将大括号视为文字字符,以便 srcFile.txt

stringA=这是字符串A:{0}

不将stringToCopy设置为


有点混乱,我们将添加一些专门用于大括号的额外编码

当前情况:

$ awk '/This is string A: {0}/{getline; print}' srcFile.txt
text to copy: {0}                   # this is the line we want
Other junk                          # we do not want this line
我们可以通过在搜索模式中转义大括号来消除第二行,例如:

$ awk '/This is string A: \{0\}/{getline; print}' srcFile.txt
text to copy: {0}
那么,如何摆脱牙套呢?我们可以使用一些显式参数展开,在$stringA变量中用转义大括号替换大括号,请记住,我们也需要在参数展开阶段转义大括号:

$ stringA="This is string A: {0}"
$ stringA="${stringA//\{/\\{}"      # replace '{' with '\{'
$ stringA="${stringA//\}/\\}}"      # replace '}' with '\}'
$ echo "${stringA}"
This is string A: \{0\}
然后,我们可以按原样继续执行代码的其余部分:

$ replacement="/$stringA/{getline; print}"
$ echo "${replacement}"
/This is string A: \{0\}/{getline; print}

$ stringToCopy="$(awk "$replacement" $srcFile)"
$ echo "${stringToCopy}"
text to copy: {0}
至于sed的最后一步,我必须移除!要使其正常工作,请执行以下操作:

$ sed -i "/$stringB/b;n;c${stringToCopy}" $outputFile
$ cat "${outputFile}"
This is string B
text to copy: {0}
注:

如果你用set-xv作为编码的开始,你可以看到变量在每个步骤中是如何被解释的;使用set+xv关闭 显然,如果在$srcFile中有多个匹配行,您可能会遇到问题 如果发现需要转义的其他字符,则需要为所述字符添加额外的参数扩展
工作方法是将变量的内容写入临时文件,并使用rsed命令。
$ stringA="This is string A: {0}"
$ stringA="${stringA//\{/\\{}"      # replace '{' with '\{'
$ stringA="${stringA//\}/\\}}"      # replace '}' with '\}'
$ echo "${stringA}"
This is string A: \{0\}
$ replacement="/$stringA/{getline; print}"
$ echo "${replacement}"
/This is string A: \{0\}/{getline; print}

$ stringToCopy="$(awk "$replacement" $srcFile)"
$ echo "${stringToCopy}"
text to copy: {0}
$ sed -i "/$stringB/b;n;c${stringToCopy}" $outputFile
$ cat "${outputFile}"
This is string B
text to copy: {0}