bit*_*bit 4 command-line shell bash quoting command-substitution
我发现在将文本作为另一个程序的输入写入时,预期文本中双引号中的任何命令替换都会被 shell 解释和扩展
此处答案中的链接指出单引号可用于防止参数扩展或命令替换。但是我发现用单引号括起命令替换也无法阻止 shell 扩展命令替换
您如何防止 shell 解释旨在作为文本而不是要执行的命令的命令替换?
$ echo "`wc -l *`"
Run Code Online (Sandbox Code Playgroud)
尝试计算当前目录中所有文件的行数
$ echo "'`wc -l *`'"
Run Code Online (Sandbox Code Playgroud)
结果相同,即计算当前目录下所有文件的行数
更新从这个演示中我发现问题似乎是我引用了单引号。我认为将单引号和`(反引号)括在双引号中可以保留(即抑制)单引号的字面意义,但不会保留引入命令替换的反引号(即反引号)的字面含义。
在我的用例中,需要引用另一个命令的输入。这份文件说:
单引号内不能出现单引号
当单引号命令替换在(双)引号字符串中时,如何防止单引号命令替换被扩展?除了使用反斜杠转义之外,应该有办法做到这一点
在程序中,我使用将任务描述分成单独行的唯一方法是用双引号将描述括起来:
$ task add "first line doesn\'t say much
Second line says a lot but part of this line does not appear in the resulting description 'truncate -s0 !(temp_file | temp_dir)' truncates all files to 0 bytes as shown by: '`wc -l *`'"
Run Code Online (Sandbox Code Playgroud)
结果描述:
first line doesn\ -s0 !(temp_file | temp_dir)' truncates all files to 0 bytes as shown by: 0 file1 10 file2 0 directory1 0 directory2 502 file3 123 file4 162 file5 0 directory3
Run Code Online (Sandbox Code Playgroud)
如你看到的
't say much
Second line says a lot but part of this line does not appear in the resulting description 'truncate
Run Code Online (Sandbox Code Playgroud)
描述中缺少,shell 已将其解释'wc -l *'为命令替换,从而将当前目录中所有文件的行数作为描述的一部分
是什么导致 shell 删除(反斜杠)和task之间的部分参数,以及如何防止 shell 解释上述单引号命令替换(即)?\-s'`wc -l *`'
Sté*_*las 11
使用单引号强引用:
printf '%s\n' '`wc -l *`'
Run Code Online (Sandbox Code Playgroud)
如果您还想在传递给 的参数中包含单引号,则printf需要为'自身使用不同的引号,例如:
printf '%s\n' '`wc -l *` and a '"'"' character'
Run Code Online (Sandbox Code Playgroud)
或者:
printf '%s\n' '`wc -l *` and a '\'' character'
Run Code Online (Sandbox Code Playgroud)
其他替代方法包括转义`双引号内的反斜杠:
printf '%s\n' "\`wc -l *\` and a ' character"
Run Code Online (Sandbox Code Playgroud)
或者`是某些扩展的结果:
backtick='`'
printf '%s\n' "${backtick}wc -l *${backtick} and a ' character"
Run Code Online (Sandbox Code Playgroud)
另请注意:
cat << 'EOF'
`wc -l *` and a ' character and a " character
EOF
Run Code Online (Sandbox Code Playgroud)
输出任意文本而不必担心引用(注意第一个周围的引号EOF)。
你也可以这样做:
var=$(cat << 'EOF'
echo '`wc -l *`'
EOF
)
Run Code Online (Sandbox Code Playgroud)
与ksh93或mksh可以优化到:
var=$(<<'EOF'
echo '`wc -l *`'
EOF
)
Run Code Online (Sandbox Code Playgroud)
(也适用于zsh,但仍运行cat在子shell那里)为$var遏制字面上echo '`wc -l *`'。
在fish外壳,可以嵌入'内'...'有\':
printf '%s\n' '`wc -l *` and a \' character'
Run Code Online (Sandbox Code Playgroud)
但无论如何`都不是特别的,所以:
printf '%s\n' "`wc -l *` and a ' character"
Run Code Online (Sandbox Code Playgroud)
也会起作用。
在 rc、es 或 中zsh -o rcquotes,您可以'在'...'with 中插入一个'':
printf '%s\n' '`wc -l *` and a '' character'
Run Code Online (Sandbox Code Playgroud)
请参阅如何将特殊字符用作普通字符?更多细节。
在这里(添加换行符),
$ task add "first line doesn\'t say much
Second line says a lot but part of this line does not appear in the
resulting description 'truncate -s0 !(temp_file | temp_dir)' truncates
all files to 0 bytes as shown by: '`wc -l *`'"
Run Code Online (Sandbox Code Playgroud)
整个字符串用双引号引起来,因此命令替换和其他扩展将在那里运行。这种情况发生在 shell 中,在task看到该字符串之前,您需要使用反斜杠或将该部分放在单引号中来防止它。
例如
$ printf "%s\n" "...shown by: '\`wc -l *\`'"
...shown by: '`wc -l *`'
Run Code Online (Sandbox Code Playgroud)
所以,
task add "...shown by: '\`wc -l *\`'"
Run Code Online (Sandbox Code Playgroud)
会将字符串传递...shown by: '`wc -l *`'给task. 这取决于它做什么。
如果您不想使用反斜杠,可以将其放在单引号中:
# aaaaaaaaaaaaaaaaBBBBBBBBBBBaaa
$ printf "%s\n" "...shown by: '"'`wc -l *`'"'"
...shown by: '`wc -l *`'
Run Code Online (Sandbox Code Playgroud)
(a' 标记双引号部分,B' 标记单引号部分。它们只是在 shell 命令行上连接起来。单引号文字位于双引号字符串内。)
至于单引号和反斜杠,您不需要转义双引号内的单引号,实际上反斜杠将保留在那里:
$ printf "%s\n" "foo'bar"
foo'bar
$ printf "%s\n" "foo\'bar"
foo\'bar
Run Code Online (Sandbox Code Playgroud)
从您所显示的情况来看,似乎task至少从参数中删除了第一个单引号字符串(之后加上一个单词,因为删除的部分是't say much ... 'truncate)
shell不会这样做,这工作正常:
$ printf "%s\n" "a 'quoted string' to test"
a 'quoted string' to test
Run Code Online (Sandbox Code Playgroud)
是什么导致 shell 删除(反斜杠) 和,
task之间的参数部分\-s
很可能不是 shell 这样做的。
以及如何防止 shell 解释上述单引号命令替换(即
'`wc -l *`')?
它不是单引号,而是双引号,旁边有单引号。