我需要使用如下语法运行命令:
runuser -l userNameHere -c '/path/to/command arg1 arg2'
不幸的是,我必须在命令本身中嵌入额外的'
个字符,我不能告诉bash正确解释这些字符。我想要运行的命令实际上是:
runuser -l miner -c 'screen -S Mine -p 0 -X eval 'stuff "pwd"\015''
不幸的是,bash似乎正在击中第二个'
并且呕吐。这是错误:
-bash: screen -S Mine -p 0 -X eval stuff: No such file or directory
,显然它没有超越'
。
如何将此作为一个命令嵌套?谢谢!
答案 0 :(得分:7)
您可以使用bash
,$'...'
支持的其他类型的引用。这可以包含转义的单引号。
runuser -l miner $'screen -S Mine -p 0 -X eval \'stuff "pwd"\015\''
请注意,在$'...'
中,\015
将被替换为代码点015处的实际ASCII字符,因此,如果这不是您想要的,则还需要转义反斜杠。
runuser -l miner $'screen -S Mine -p 0 -X eval \'stuff "pwd"\\015\''
我认为您可以利用$'...'
来消除对eval
的需求:
runuser -l miner $'screen -S Mine -p 0 -X stuff "pwd"\015'
答案 1 :(得分:5)
命令本身没有看到外部引号。 shell使用那些来避免单词分裂,但不会让命令知道它们在那里。所以如果你有:
./command foo bar "baz biz"
该命令看到三个args, foo , bar 和 baz biz ,其中空格完整,但没有引号。因此,如果你需要实际发送引号,你可以通过用另一种引用包装参数来做到这一点:
./command "foo'bar"
该命令会看到一个arg: foo' bar 。但是如果你需要发送两种类型的引号,你就有一个难以解决的问题。你可以用倾斜的牙签,报价交换或变量解决它:
即使shell使用引号来避免单词分裂,如果你将引用的参数放在彼此旁边而没有空格,命令会将它看作一个单词:
./command "foo""bar"
该命令会看到一个arg: foobar 。因此,如果您使用两种不同的报价:
./command 'foo"bar'"baz'quux"
命令会看到一个arg: foo" barbaz' quux 。
有两种倾斜的牙签。一个是真正的报价交换,除非你不使用引号来包装其中一个...引用。
./command 'foo"barbaz'\'quux
命令会看到一个arg: foo" barbaz' quux 。另一个是(帽子提示:chepner)使用特殊的$'string'
形式的单词扩展,它允许ANSI C字符串:
./command $'foo"barbaz\'quux'
命令会看到一个arg: foo" barbaz' quux 。
doublequote=\" singlequote=\'
./command "foo${doublequote}barbaz${singlequote}quux"
命令会看到一个arg: foo" barbaz' quux 。
答案 2 :(得分:1)
您不能在单引号中嵌套单引号。您可以通过转义双引号来嵌套双引号。
使用单引号可以做的最好的事情就是在需要嵌入单引号的地方使用'\''
。
这是结束单引号字符串的单引号。一个不带引号但却逃脱的单引号。并使用单引号开始下一个单引号字符串。
答案 3 :(得分:1)
请参阅我的回答here。基本上,你不能将单引号放在单引号内 - 但是你不必这样做,因为引号不是单词分隔符,所以你可以跳出引号,关闭{{1现在,您使用'
在引号之外添加一个文字单引号,然后使用新的\'
返回引号,所有这些都不会终止当前的shell字。
答案 4 :(得分:1)
不是手动转义,而是可以让shell为你做这件事并避免麻烦(如果你的shell是bash
;这是POSIX sh中没有的扩展,所以你的shebang需要是#!/bin/bash
,而非#!/bin/sh
)。
例如:
printf -v command '%q ' /path/to/command arg1 arg2
printf -v outer_command '%q ' runasuser -l userNameHere -c "$command"
printf -v ssh_command '%q ' ssh hostname "$outer_command"
...会在"$ssh_command"
中添加一个字符串,如果进行评估,它将在runasuser
内的ssh
内运行内部命令。
提供一些构造如何使用这些变量的例子:
# this evaluates the command in the current shell in a sane way
ssh hostname "$outer_command"
# this evaluates the command in the current shell in an inefficient way
eval "$ssh_command"
# this evaluates the command in a new shell
bash -c "$ssh_command"
# this evaluates the command in a new shell as a different user
sudo -u username bash -c "$ssh_command"
# this writes the command to a script, and makes it executable
printf '%s\n' "#!/bin/bash" "$ssh_command" >run_ssh
chmod +x run_ssh
提供一些示例,说明 NOT 如何使用这些变量:
# DO NOT DO THESE: WILL NOT WORK
$ssh_command # see http://mywiki.wooledge.org/BashFAQ/050
"$ssh_command" # likewise
sudo "$ssh_command" # likewise