为什么 grep 用星号搜索的文件比我想要的文件多?

为什么 grep 用星号搜索的文件比我想要的文件多?

我在 bash 脚本深处

grep -Ech 'string1|string2' /server/directory/$servername_log_20150312* | awk ...

我收到“参数太多”错误,因此我打开set -x文件,发现 grep 正在尝试从以下文件开始搜索

/server/directory/$servername_log_20150101.000001.log   # Notice the date disparity.

每个字符串中的都$servername使用循环迭代的值进行正确扩展。为什么 grep 不将自身限制为以我指定的字符串开头的文件名?

答案1

问题

让我们从定义服务器名称开始:

$ servername=SomeName

现在尝试:

$ echo "$servername_log_20150312"

$

上面没有返回任何内容,因为 (a) 下划线是 shell 变量名中的合法字符,并且 (b) 我们从未定义过servername_log_20150312

现在考虑:

/server/directory/$servername_log_20150312*

变量展开后,变成:

/server/directory/*

路径名扩展后,上面成为目录中的每个文件。

两种解决方案

因为这种事情很常见,所以 shell 对变量有大括号表示法:

$ echo "${servername}_log_20150312"
SomeName_log_20150312

将名称与后面的字符分开的其他方法也是可能的:

$ echo "$servername""_log_20150312"
SomeName_log_20150312

文档

从 开始man bash,变量名称可以包含字母数字字符和下划线的任意组合,但必须以字母字符开头:

   name   A word consisting only of alphanumeric characters  and  underscores,  and
          beginning  with  an alphabetic character or an underscore.  Also referred
          to as an identifier.

POSIX使变量名称的限制依赖于实现。虽然它要求 shell 接受名称中的字母数字和下划线,但它似乎为 shell 提供了接受除=和 NUL 之外的任何内容的选项。

答案2

@john1024 正确指出了我脚本中的错误。运行 grep 命令时,shell 正在查找变量,$servername_log_20150312而不是$servername按预期查找。

抵消它就"$servername"解决了问题。

我认为 grep 的行为很奇怪,因为我在 grep 的输入中看到了所有预期的服务器名称。但这是一个技巧,因为它实际上无法找到变量$servername_log_20150312并默认搜索整个目录。事实上,在达到 grep 的最大参数限制之前,所有所需的服务器名称都出现在目录中,这进一步掩盖了真正的原因。

相关内容