我在 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 的最大参数限制之前,所有所需的服务器名称都出现在目录中,这进一步掩盖了真正的原因。