[英]grep output different in bash script
我正在创建一个bash脚本,该脚本将仅使用grep来查看一堆日志中的某个字符串。
有趣的事情发生了。
为了测试所有日志文件,文件被命名为test1.log,test2.log,test3.log等。
使用grep命令时:
grep -oHnR TEST Logs/test*
输出包含预期的文件夹中所有文件的所有实例。
但是当使用命令但包含在下面的bash脚本中时:
#!/bin/bash
#start
grep -oHnR $1 $2
#end
输出仅显示1个文件中的实例。
运行脚本时,我使用以下命令:
bash test.bash TEST Logs/test*
这是预期输出的示例(仅使用grep时会发生的情况):
Logs/test2.log:8:TEST
Logs/test2.log:20:TEST
Logs/test2.log:41:TEST
Logs/test.log:2:TEST
Logs/test.log:18:TEST
这是使用bash脚本时收到的输出示例:
Logs/test2.log:8:TEST
Logs/test2.log:20:TEST
Logs/test2.log:41:TEST
有人可以向我解释为什么会这样吗?
拨打电话时
bash test.bash TEST Logs/test*
这将由外壳程序翻译为
bash test.bash TEST Logs/test1.log Logs/test2.log Logs/test3.log Logs/test4.log
(如果您有四个日志文件)。
命令行参数TEST
, Logs/test1.log
, Logs/test2.log
等将被赋予名称$1
, $2
, $3
等。 $1
将是TEST
, $2
将是Logs/test1.log
。
仅使用$2
时,您只需忽略其余参数,仅使用一个日志文件。
正确的版本是这样的:
#!/bin/bash
#start
grep -oHnR "$@"
#end
这样可以正确地传递所有参数,还可以处理文件名中的空格之类的麻烦事情(您的版本可能会遇到麻烦)。
要了解发生了什么,可以使用一个更简单的脚本:
#!/bin/bash
echo $1
echo $2
根据您的要求,输出前两个参数。
您要使用第一个参数,然后将其余所有参数用作输入文件。 因此,使用shift
这样:
#!/bin/bash
search=$1
shift
echo "$1"
echo "$@"
还请注意使用双引号。
在您的情况下,因为您希望将搜索字符串和文件名以相同的顺序传递到grep
,所以您甚至不需要shift
:
#!/bin/bash
grep -oHnR -e "$@"
(我添加了-e
以防搜索字符串以-
开头)
未加引号*
受着通配符 ,当你调用脚本。
使用set -x
输出脚本中正在运行的内容可以使这一点更加清楚。
$ ./greptest.sh TEST test*
++ grep -oHnR TEST test1.log
$ ./greptest.sh TEST "test*"
++ grep -oHnR TEST test1.log test2.log test3.log
在第一种情况下,bash将*扩展到文件名列表,而第二种情况是将bash传递给grep。 在第一种情况下,您实际上有> 2个args(因为扩展的每个文件名都将成为arg)-在脚本中添加echo $#
也会显示以下内容:
$ ./greptest.sh TEST test*
++ grep -oHnR TEST test1.log
++ echo 4
4
$ ./greptest.sh TEST "test*"
++ grep -oHnR TEST test1.log test2.log test3.log
++ echo 2
2
您可能想在bash调用中转义通配符:
bash test.bash TEST Logs/test\*
这样,它将以*
传递给grep,否则shell会将其扩展到Logs目录中名称以test
开头的每个文件。
或者,更改脚本以在命令行上允许多个文件:
#!/bin/bash
hold=$1
shift
grep -oHnR $hold $@
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.