概要:“tmux send-keys”从 bash 命令中删除空格,我不明白为什么(或者如何,真的。)
test ()
{
tmux new -s testsession -d
tmux send-keys -t testsession "time tar -I \"zstd -19 -T0\" -cvf ${1}.tar.zst "${@:2}""
tmux attach -t testsession
}
输入
输入1 输入2 输入3 i\ n\ p\ u\ t\ 4
预期(和期望)的输出是
时间 tar -I "zstd -19 -T0" -cvf input1.tar.zst "input2" "input3" "i n 把你 4 英寸
相反我得到了
时间 tar -I“zstd -19 -T0”-cvf input1.tar.zst“input2input3input4”
注意我省略了发送键末尾的
; C-m
或 ; ENTER
。 (而且我还简化了原始函数,因为其他部分更简单、更有效。)我这样做是为了更准确地理解昨晚花了几个小时试图暴力破解终端上输出的内容。 “正确”语法(无济于事。)
我偶然发现了同样的问题,我发现了为空格添加关键字“Space”的不太好的解决方案。
所以,在你的情况下,我希望以下命令能够工作:
tmux send-keys -t testsession "time Space tar Space -I Space \"zstd Space -19 Space -T0\" Space -cvf Space ${1}.tar.zst Space "${@:2}""
我从本页的发送密钥描述“密钥列表”部分得到了这个想法。
使用
"$*"
代替 "$@"
:
tmux send-keys -t bar "$*" C-m
"$*"
将参数表示为单个字符串,而不是拆分为数组。
使用
"$@"
时,即使用引号括起来,单词边界也会保留,因此将 "$@"
发送到另一个程序会单独发送每个输入。这使得将输入从包装函数传递到另一个函数变得很容易。
$@
和"$@"
之间的区别在于,虽然"$@"
保留参数分割,但它不会进一步分割它。请参阅shellcheck wiki。
我用于测试的脚本,
test.sh
:
#!/bin/sh
printargs()
{
echo "\$1: $1"
echo "\$2: $2"
echo "\$3: $3"
}
foo="$@"
printargs $@
printargs "$@"
printargs $*
printargs "$*"
printargs $(echo "$@")
printargs "$(echo "$@")"
printargs $foo
printargs "$foo"
调用
./test.sh foo 'bar baz'
打印到终端:
$1: foo
$2: bar
$3: baz
$1: foo
$2: bar baz
$3:
$1: foo
$2: bar
$3: baz
$1: foo bar baz
$2:
$3:
$1: foo
$2: bar
$3: baz
$1: foo bar baz
$2:
$3:
$1: foo
$2: bar
$3: baz
$1: foo bar baz
$2:
$3:
我正在使用
dash
,一个符合 POSIX 标准的 shell,但使用 bash
运行它会产生相同的结果。
一种方法是使用 shell 参数扩展与 E 运算符:
function quote() { for arg; do echo \"$arg\"; done | paste -sd' ' ; }
function test() {
tmux new -s testsession -d
command="time tar -I \"zstd -19 -T0\" cvf ${1}.tar.zst $(quote "${@:2}")"
tmux send-keys -t testsession "${command@E}"
tmux attach -t testsession
}
然后运行命令
test input1 input2 input3 i\ n\ p\ u\ t\ 4
将我们附加到一个 tmux 窗口,并将密钥发送给它:
$ time tar -I "zstd -19 -T0" cvf input1.tar.zst "input2" "input3" "i n p u t 4"
一般解释:来自 tmux 手册页:
每个参数键是要发送的键的名称(例如“C-a”或“NPage”); 如果字符串未被识别为密钥,则会作为一系列字符发送。
所以这里的报价有两个层次。您的 shell 正在解释带引号的字符串,然后将其发送到 tmux,tmux 再次读取并解释您发送的字符串,即外部引号的内容。这有点像在信封里寄一封信。这样
tmux send-keys -t session-name "echo \"hello world!\""
将
echo "hello world!"
放在控制台上。 (如果您得到 bash: !\": event not found
,请确保首先使用 set +H
关闭历史记录扩展。)
它将您的字符串读取为字符序列,因为
echo "hello world!"
不是键的名称。
更具体的解释:我将
"${@:2}"
更改为一个函数,该函数显式地在每个参数周围写入引号,并将它们与中间的空格连接起来。 (我的函数必须调用 echo
和 paste
,因此可能有一种更优雅的方法可以在 bash 中执行此操作。)
${command@E}
语法使用 E 运算符,在 bash 手册中这样定义:
扩展是一个字符串,它是带有反斜杠转义序列的参数值,与 $'...' 引用机制一样扩展。
$'...'
引用机制是ANSI-C引用标准。换句话说,${command@E}
转义了$command
中的所有麻烦字符,就像在 C 中转义它们一样。Tmux 似乎对这个引用标准很满意,尽管我找不到任何这么说的文档。