首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止命令行上的命令替换?

如何防止命令行上的命令替换?
EN

Unix & Linux用户
提问于 2019-07-29 20:12:14
回答 4查看 4.7K关注 0票数 5

我发现当将文本写成另一个程序的输入时,任何在预期文本中双引号中的命令替换都会被shell解释和扩展。

答案这里中的链接指出,单引号可用于防止参数展开或命令替换。但是,我发现在单引号中包含命令替换也不能阻止shell展开命令替换。

如何防止shell解释作为文本而不是要执行的命令的替换命令?

A演示

代码语言:javascript
复制
$ echo "`wc -l *`"

尝试计算当前目录中所有文件中的行数。

代码语言:javascript
复制
$ echo "'`wc -l *`'"

相同的结果,即计算当前目录中所有文件中的行数。

更新从这个演示中我发现问题似乎是我引用了单引号。我认为在双引号中包含单引号和` (回勾),保留字面意思 (即取消)单引号,但不保留引入命令替换的反引号(即回勾)的字面意义。

在我的用例中,需要引用另一个命令的输入。这个文档说:

单引号不能出现在单引号中。

当单引号命令替换在(双)引号字符串内时,如何防止单引号命令替换被展开?除了使用反斜杠转义之外,还应该有一种方法来完成它。

实际情况

在一个程序中,我使用的唯一方法是将任务描述拆分成不同的行,将描述用双引号括起来:

代码语言:javascript
复制
$ 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 *`'"

由此产生的说明:

代码语言:javascript
复制
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

如你所见

代码语言:javascript
复制
't say much
Second line says a lot but part of this line does not appear in the resulting description 'truncate

'wc -l *'解释为命令替换,从而将当前目录中所有文件的行数作为描述的一部分包括在内。

是什么原因导致shell移除task\ (反斜杠)和-s之间的部分参数,以及如何防止shell解释上面单引号的命令替换(即'`wc -l *`')?

EN

回答 4

Unix & Linux用户

回答已采纳

发布于 2019-07-31 05:53:12

在这里(加了行符),

代码语言:javascript
复制
$ 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 *`'"

整个字符串都是双引号,因此命令替换和其他扩展将在那里运行。这种情况发生在shell中,在task看到该字符串之前,您需要使用反斜杠或将该部分放在单引号中来防止它。

例如。

代码语言:javascript
复制
$ printf "%s\n" "...shown by: '\`wc -l *\`'"
...shown by: '`wc -l *`'

所以,

代码语言:javascript
复制
task add "...shown by: '\`wc -l *\`'"

将字符串...shown by: '`wc -l *`'传递给task。这取决于它是怎么做的。

如果您不想使用反斜杠,下面是将其放入单引号的方法:

代码语言:javascript
复制
#               aaaaaaaaaaaaaaaaBBBBBBBBBBBaaa
$ printf "%s\n" "...shown by: '"'`wc -l *`'"'"
...shown by: '`wc -l *`'

( a's标记双引号,B's表示单引号。它们只是在shell命令行上连在一起。文字单引号在双引号内。)

至于单引号和反斜杠,您不需要在双引号中转义单引号,实际上反斜杠仍然存在:

代码语言:javascript
复制
$ printf "%s\n" "foo'bar"
foo'bar
$ printf "%s\n" "foo\'bar"
foo\'bar

从您所显示的情况来看,task似乎至少从参数中删除了第一个单引号字符串(加上后面的一个单词,因为删除的部分是't say much ... 'truncate)。

shell将而不是这样做,这很好:

代码语言:javascript
复制
$ printf "%s\n" "a 'quoted string' to test"
a 'quoted string' to test

是什么导致shell移除task\ (反斜杠)和-s之间的参数部分,

很可能不是贝壳干的。

如何防止shell解释上述单引号命令替换(即'`wc -l *`')?

它不是单引号,而是双引号,旁边是单引号。

票数 4
EN

Unix & Linux用户

发布于 2019-07-29 21:38:11

使用单引号强引用:

代码语言:javascript
复制
printf '%s\n' '`wc -l *`'

如果希望在传递给printf的参数中也包括单引号,则需要对'本身使用不同的引号,例如:

代码语言:javascript
复制
printf '%s\n' '`wc -l *` and a '"'"' character'

或者:

代码语言:javascript
复制
printf '%s\n' '`wc -l *` and a '\'' character'

其他选择包括在双引号中使用反斜杠转义`

代码语言:javascript
复制
printf '%s\n' "\`wc -l *\` and a ' character"

或者让`是某些扩展的结果:

代码语言:javascript
复制
backtick='`'
printf '%s\n' "${backtick}wc -l *${backtick} and a ' character"

还请注意:

代码语言:javascript
复制
cat << 'EOF'
`wc -l *` and a ' character and a " character
EOF

输出任意文本而不必担心引用(注意第一个EOF周围的引号)。

你也可以:

代码语言:javascript
复制
var=$(cat << 'EOF'
echo '`wc -l *`'
EOF
)

使用ksh93mksh,您可以将其优化为:

代码语言:javascript
复制
var=$(<<'EOF'
echo '`wc -l *`'
EOF
)

(也可以在zsh中工作,但仍然在子still中运行cat ),以便$var包含字面意义上的echo '`wc -l *`'

fish外壳中,可以使用\''嵌入到'...'中:

代码语言:javascript
复制
printf '%s\n' '`wc -l *` and a \' character'

但是无论如何,`在那里并不特别,所以:

代码语言:javascript
复制
printf '%s\n' "`wc -l *` and a ' character"

也能起作用。

在rc、es或zsh -o rcquotes中,您可以使用'''...'中插入一个D29

代码语言:javascript
复制
printf '%s\n' '`wc -l *` and a '' character'

有关更多详细信息,请参阅如何使用一个特殊的字符作为一个正常的?

票数 11
EN

Unix & Linux用户

发布于 2019-07-29 21:14:27

您可以使用反斜杠转义反斜杠,如下所示:

代码语言:javascript
复制
echo "\`wc -l *\`"
票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/532811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档