我想在 bash 脚本中执行一些命令。
现在,当我们使用单引号时,变量将被视为文字而不是值。
因此,执行 egls "$SOME_DIR"
与ls '$SOME_DIR'
我们如何处理引号和双引号的混合不同,而不是所有内容都因转义双引号而变得混乱?
例如如何验证类似的内容:
ssh server.com "mkdir \"/foo/bar/"$final"\""
由于命令越长,它变得不可读并且很容易被破坏,我怎样才能避免所有这些转义?
答案1
经过多次使用heredocs
和herestrings
,似乎最简单的解决方案是这样的:
ssh server.com "mkdir '/foo/bar/$final'"
是的,尽管有单引号bash
,仍将进行变量替换$final
,就像在echo "test'$final'"
.
$final
注意:正如@muru 所指出的,如果包含单引号,这将不起作用。
答案2
相反的引用,(IE双引号中的单引号,以及反之亦然),可以代替转义。不使用转义符或这里的文件,考虑如何使用echo
来显示此文本:
他头也不回,说道:“没办法。”
用双引号或单引号将其引起来是行不通的。交替使用相反的引号确实有效:
echo "He didn't look back, and said "'"It can'"'t be helped."'"'
输出:
He didn't look back, and said "It can't be helped."
不幸的是,上面的echo
内容和转义一样难以阅读。
快乐的媒介是使用相反的引号并根据需要转义两者以减少视觉单调:
echo "He didn't look back, and said \"It can't be helped.\""
应用于代码:
ssh server.com 'mkdir "'"/foo/bar/$final"\"
即使$final
包含'
.
展开报价,我们有:
'mkdir "'
,它保留一个空格和一个左双引号。"/foo/bar/$final"
$final
它返回启动之前的内容ssh
。\"
关闭双引号,保留目录名ssh
答案3
我认为真正的需求很大程度上取决于您希望在何处/何时扩展变量 - 在本地发送命令之前或在远程发送命令之后。两种情况都是有效的。无论哪种方式,如果您的命令适合一行,我建议您<<<
分别使用双引号或单引号来重定向命令
1.发送命令前解析变量
final="defined_locally"; ssh server.com <<<"final="defined_remotely" ;mkdir /foo/bar/"$final" "
2. 发送命令后解析变量
final="defined_locally"; ssh server.com <<<'final="defined_remotely"; mkdir /foo/bar/"$final" '
第一个将创建
/foo/bar/define_locally
第二个将创建
/foo/bar/define_remotely
远程服务器上的目录
正如您所看到的,在这两种情况下都不需要转义,直到您想在一个命令中混合本地和远程定义的变量。
更新:
<<<
严格来说不是重定向,而是这里字符串
更新2:
感谢@Rastapopoulos 指出
Pseudo-terminal will not be allocated because stdin is not a terminal
伴随命令执行的消息
虽然没有什么坏处
答案4
这是内置的工作吗printf
?
ldo@theon:~> f='He didn'\''t look back, and said "It can'\''t be helped."'
ldo@theon:~> echo "$f"
He didn't look back, and said "It can't be helped."
ldo@theon:~> ssh hypatia echo "$f"
bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file
ldo@theon:~> ssh hypatia echo $(printf %q "$f")
He didn't look back, and said "It can't be helped."