Bash 在远程服务器上的文件匹配后,如何将包含特殊字符的字符串插入该文件

Bash 在远程服务器上的文件匹配后,如何将包含特殊字符的字符串插入该文件,bash,sed,awk,special-characters,Bash,Sed,Awk,Special Characters,我有一个包含制表符和换行符的字符串,需要在远程服务器上的文件中的特定位置(匹配后)插入这些制表符和换行符 我知道如何将字符串放入远程文件: me@local$ grep string file | ssh remote "cat > otherfile" me@remote$ cat otherfile string:foo string:bar 但是,我想在otherfile中的特定匹配之后插入grep的结果。在本地,我可以通过保存grep结果,然后在sed命令中像疯子一样引用所有内容

我有一个包含制表符和换行符的字符串,需要在远程服务器上的文件中的特定位置(匹配后)插入这些制表符和换行符

我知道如何将字符串放入远程文件:

me@local$ grep string file | ssh remote "cat > otherfile"
me@remote$ cat otherfile
string:foo
string:bar
但是,我想在
otherfile
中的特定匹配之后插入
grep
的结果。在本地,我可以通过保存
grep
结果,然后在
sed
命令中像疯子一样引用所有内容:

me@local$ foo="$(grep string file)"
me@local$ sed -i "/^### MATCH ###/ a "${foo}"" otherfile
me@local$ cat otherfile
### MATCH ###
string:foo
string:bar
最后一步我很费劲,比赛结束后远程插入
grep
结果。不幸的是,这两种解决方案都不起作用:

me@local$ foo="$(grep string file)"
me@local$ ssh remote sed -i "/^### MATCH ###/ a "${foo}"" otherfile
sed: -e expression #1, char 5: unterminated address regex
me@local$ grep string file | ssh remote "cat | sed -i \"/^### MATCH ###/ a\\\" otherfile"
bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file
编辑我通过使用更多的quote magic取得了一些进展,但换行符似乎没有很好地转换:

me@local$ foo="$(grep string file)"
me@local$ ssh remote sed -i \"/^###\ MATCH\ ###/ a \'${foo}\'\" otherfile
me@remote$ cat otherfile
### MATCH ###
'string:foo string:bar'
More quote magic尚未真正解决此问题:

me@local$ foo="$(grep string file)"
me@local$ ssh remote sed -i \"/^###\ MATCH\ ###/ a ${foo}\" otherfile
me@remote$ cat otherfile
### MATCH ###
string:foo string:bar
可能的解决方案编辑:我使用
printf
有一个非常难看的解决方案:

tmp=$(printf "%q" "$(grep string file)")
# because printf may add $'' around the string
[ "${tmp:0:2}" = "$'" ] && tmp="${tmp:2}" && tmp="${tmp%?}"
ssh remote "sed -i \"/^### MATCH ###/ a ${tmp}\" otherfile" < /dev/null
tmp=$(printf“%q”“$(grep字符串文件))
#因为printf可能会在字符串周围添加$“”
[“${tmp:0:2}”=“$”]&&tmp=“${tmp:2}”&&tmp=“${tmp%?}”
ssh远程“sed-i\”/^#########/a${tmp}\“其他文件”

但我觉得这太令人厌恶了,我不想把它作为一个答案,希望其他人能以稍微优雅一点的方式回答。

避免逃逸bug的最好方法是根本不要逃逸。 由于
sed
支持从文件中读取命令字符串,因此需要使其从stdin中读取,如第一个示例所示

me@local$ foo="$(grep string file)"
me@local$ sedcmd="/^### MATCH ###/ a "${foo}""
me@local$ echo "$sedcmd" | ssh remote sed -f /dev/stdin otherfile
如果您的系统没有/dev/stdin,请尝试
/dev/fd/0

“#因为printf可能会在字符串周围添加$”。您是否使用shell调试/跟踪、
set-vx
进行测试?您描述的内容听起来像是std_err输出的调试工件。除非您在使用
set-vx
时将std\u err输出重定向到std\u out,否则我认为一旦您通过隐藏
set-vx
或使用
set+vx
关闭调试,您将发现额外的
$'…
内容已经消失,并且您确实拥有干净的字符串。祝你好运。另外,(我现在没有办法测试),你试过
ssh-remote-c'sed…
?此外,您可以获取变量值,但可以使用诸如
sed-k”/^###########/a“${foo}”等串联方式将字符串保持在一起。正如您所看到的,它确实很复杂。对于我来说,这种解决方法看起来相当不错,而对于定义良好的小测试用例来说,它没有解决方案:-)-1。祝您好运。