sta*_*fry 6 shell bash string eval bash-expansion
我有一个shell 变量,其中包含由空格分隔的多个单词bash
组成的字符串。字符串可以包含转义符,例如单词中转义的空格。包含空格的单词也可以被引用。
$FOO
不加引号(而不是)使用的 shell 变量"$FOO"
会变成多个单词,但原始字符串中的引号和转义不起作用。
如何将字符串拆分为单词,同时考虑引用字符和转义字符?
服务器提供ssh
使用文件ForceCommand
中的选项来sshd_config
强制执行脚本的受限访问,而不管向客户端提供的命令行如何ssh
。
该脚本使用变量SSH_ORIGINAL_COMMAND
(它是一个字符串,由 设定ssh
,包含提供给客户端的命令行ssh
)在继续之前设置其参数列表。所以,用户做
$ ssh some_server foo 'bar car' baz
Run Code Online (Sandbox Code Playgroud)
将看到脚本执行,并且当脚本执行时它将设置为四个SSH_ORIGINAL_COMMAND
参数foo bar car baz
set -- ${SSH_ORIGINAL_COMMAND}
Run Code Online (Sandbox Code Playgroud)
不是想要的结果。于是用户再次尝试:
$ ssh some_server foo bar\ car baz
Run Code Online (Sandbox Code Playgroud)
相同的结果 - 第二个参数中的反斜杠需要为客户端 shell 进行转义,以便ssh
看到它。这些怎么样:
$ ssh some_server foo 'bar\ car' baz
$ ssh some_server foo bar\\ car baz
Run Code Online (Sandbox Code Playgroud)
两者都可以工作,就像可以简化客户端引用的printf "%q"
引用包装器一样。
客户端引用允许ssh
将正确引用的字符串发送到服务器,以便服务器接收到的SSH_ORIGINAL_COMMAND
反斜杠完好无损:foo bar\ car baz
。
但是仍然存在问题,因为set
没有考虑引用或转义。有一个解决方案:
eval set -- ${SSH_ORIGINAL_COMMAND}
Run Code Online (Sandbox Code Playgroud)
但这是不可接受的。考虑
$ ssh some_server \; /bin/sh -i
Run Code Online (Sandbox Code Playgroud)
非常不可取:eval
无法使用,因为无法控制输入。
需要的是eval
没有执行部分的字符串扩展能力。
使用read
:
read -a ssh_args <<< "${SSH_ORIGINAL_COMMAND}"
set -- "${ssh_args[@]}"
Run Code Online (Sandbox Code Playgroud)
这会将单词解析SSH_ORIGINAL_COMMAND
到数组中ssh_args
,并将反斜杠 ( \
) 视为转义字符。然后将数组元素作为参数给出set
。它适用ssh
于像这样传递的参数列表:
$ ssh some_server foo 'bar\ car' baz
$ ssh some_server foo bar\\ car baz
Run Code Online (Sandbox Code Playgroud)
$ sshwrap some_server foo bar\ car baz
$ sshwrap some_server foo 'bar car' baz
Run Code Online (Sandbox Code Playgroud)
这是一个这样的包装示例:
#!/bin/bash
h=$1; shift
QUOTE_ARGS=''
for ARG in "$@"
do
ARG=$(printf "%q" "$ARG")
QUOTE_ARGS="${QUOTE_ARGS} $ARG"
done
ssh "$h" "${QUOTE_ARGS}"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3768 次 |
最近记录: |