use*_*028 5 linux bash quotes command-line gnu-screen
我需要使用如下语法运行命令:
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,显然它没有超越'.
如何将其作为一个命令嵌套?谢谢!
您可以使用其他类型的引用bash,$'...'.这可以包含转义的单引号.
runuser -l miner $'screen -S Mine -p 0 -X eval \'stuff "pwd"\015\''
Run Code Online (Sandbox Code Playgroud)
请注意,在内部$'...',\015将在代码点015处替换为实际的ASCII字符,因此如果这不是您想要的,则还需要转义反斜杠.
runuser -l miner $'screen -S Mine -p 0 -X eval \'stuff "pwd"\\015\''
Run Code Online (Sandbox Code Playgroud)
我认为你可以利用它$'...'来消除这种需要eval:
runuser -l miner $'screen -S Mine -p 0 -X stuff "pwd"\015'
Run Code Online (Sandbox Code Playgroud)
该命令本身看不到外部引号。外壳程序使用它们来避免单词拆分,但是不让命令知道它们在那里。因此,如果您有:
./command foo bar "baz biz"
Run Code Online (Sandbox Code Playgroud)
该命令将看到三个args,foo,bar和baz biz,这些空格完整无缺,但没有引号。因此,如果您需要实际发送引号,则可以通过将参数包装在另一种引号上来实现:
./command "foo'bar"
Run Code Online (Sandbox Code Playgroud)
该命令看到一个arg:foo'bar。但是,如果您需要同时发送两种报价,则您将面临一个更难解决的问题。您可以使用倾斜的牙签,引号交换或变量来解决它:
即使外壳程序使用引号来避免单词拆分,但是如果您将带引号的参数彼此相邻而没有空格,则命令会将其视为一个单词:
./command "foo""bar"
Run Code Online (Sandbox Code Playgroud)
该命令看到一个arg:foobar。因此,如果您使用两种不同的引号:
./command 'foo"bar'"baz'quux"
Run Code Online (Sandbox Code Playgroud)
该命令看到一个arg:foo“ barbaz'quux。
有两种倾斜的牙签。一种是实际上只是引用交换,只是您不使用引号来包装…引号之一。
./command 'foo"barbaz'\'quux
Run Code Online (Sandbox Code Playgroud)
该命令看到一个arg:foo“ barbaz'quux。另一个是(hat tip:chepner)使用特殊$'string'形式的单词扩展,它允许ANSI C字符串:
./command $'foo"barbaz\'quux'
Run Code Online (Sandbox Code Playgroud)
该命令看到一个arg:foo“ barbaz'quux。
doublequote=\" singlequote=\'
./command "foo${doublequote}barbaz${singlequote}quux"
Run Code Online (Sandbox Code Playgroud)
该命令看到一个arg:foo“ barbaz'quux。
您不能在单引号中嵌套单引号。您可以通过转义双引号将双引号嵌套在双引号中。
使用单引号可以做的最好的事情是'\''在需要嵌入单引号的任何地方使用。
这是结束单引号字符串的单引号。未加引号但已转义的单引号。和一个单引号开始下一个单引号字符串。
您可以要求 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"
Run Code Online (Sandbox Code Playgroud)
...将放入一个字符串,如果计算,将在inside"$ssh_command"中运行内部命令。runasuserssh
提供一些如何使用这些变量(一旦构建)的示例:
# 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
Run Code Online (Sandbox Code Playgroud)
提供一些反例,说明如何在构造后不使用这些变量:
# DO NOT DO THESE: WILL NOT WORK
$ssh_command # see http://mywiki.wooledge.org/BashFAQ/050
"$ssh_command" # likewise
sudo "$ssh_command" # likewise
Run Code Online (Sandbox Code Playgroud)