【问题标题】:Why does bash script add single quotes to string with asterisk?为什么 bash 脚本会在带有星号的字符串中添加单引号?
【发布时间】:2017-03-02 16:59:43
【问题描述】:

我正在尝试制作一个小脚本作为此命令的包装器:

$ egrep target /usr/lusers/me/test/*test.txt 
/usr/lusers/me/test/1test.txt:target

该目录包含名为 1test.txt2test.txt 的文件,其中一个包含我要查找的一些文本。
这是我的整个脚本,名为mygrep.sh

set -v
set -x
egrep "$1" '/usr/lusers/me/test/*test.txt'

这是输出:

$ ./mygrep.sh target
set -x
egrep "$1" '/usr/lusers/me/test/*test.txt'
++ egrep targ '/usr/lusers/me/test/*test.txt'
egrep: /usr/lusers/me/test/*test.txt: No such file or directory

注意set -x 输出中文件路径周围的's,并且该命令失败。

现在比较一下这个脚本的变体:

set -v
set -x
egrep "$1" '/usr/lusers/me/test/1test.txt'

请注意,唯一的区别是星号与文字文件名。
输出:

$ ./mygrep.sh target
set -x
egrep "$1" '/usr/lusers/me/test/1test.txt'
++ egrep target /usr/lusers/me/test/1test.txt
target

展开后没有单引号,命令有效。

那么,为什么在有星号时要添加这些单引号,为什么在这种情况下命令会失败?

【问题讨论】:

    标签: bash


    【解决方案1】:

    set -x 的输出用于调试目的。参数中没有添加引号;它们仅用于展示目的。

    正确的命令是egrep "$1" /usr/lusers/me/test/*.test.txt,因为shell 在将结果传递给egrep 之前必须扩展模式(如果可能)。您没有名为 *.test.txt 的实际文件。

    【讨论】:

    • 我正在考虑将星号传递给 egrep 并让它在那里扩展。我想这没关系,但这可能吗?
    • @P1h3r1e3d13 通配符(即根据表达式生成匹配的文件名)是 shell 的一项功能,而不是 egrep。如果星号指向egrep,则表示该实用程序的字面星号。
    • 实际上,作为正则表达式(而不是文件名)的一部分,星号对egrep 有特殊含义。所以请不要将我的评论解释为所有星号都是 egrep 的字面意思。
    【解决方案2】:

    通配符必须在引号之外(单引号或双引号),因为引号会禁用通配符。

    改用这个:

    egrep "$1" '/usr/lusers/me/test/'*'test.txt'
    

    或者这个:

    egrep "$1" "/usr/lusers/me/test/"*"test.txt"
    

    或者,因为在这个特定模式中没有任何东西会导致分词发生(但如果事先不知道路径是安全的,那通常不是一种安全的方法):

    egrep "$1" /usr/lusers/me/test/*test.txt
    

    【讨论】:

      猜你喜欢
      • 2016-02-25
      • 2021-09-19
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      • 2014-04-13
      • 2016-03-08
      相关资源
      最近更新 更多