grep输出在bash脚本中有所不同

问题描述 投票:0回答:4

我正在创建一个bash脚本,它只是使用grep来查看一堆特定字符串的日志。

但有些事情发生了。

为了测试所有日志文件,文件名为test 1.log,test2.log,test 3.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 command-line-arguments
4个回答
3
投票

当你拨打电话时

bash test.bash TEST Logs/test*

这将由shell翻译成

bash test.bash TEST Logs/test1.log Logs/test2.log Logs/test3.log Logs/test4.log

(如果您有四个日志文件)。

命令行参数TESTLogs/test1.logLogs/test2.log等将被命名为$1$2$3等; $1将是TEST$2将是Logs/test1.log

您只需忽略其余参数,并在仅使用$2时仅使用一个日志文件。

一个正确的版本是这样的:

#!/bin/bash
#start

grep -oHnR "$@"

#end

这将正确传递所有参数,并且还会处理文件名中的空格之类的任务(您的版本会遇到这些问题)。


2
投票

要了解发生了什么,您可以使用更简单的脚本:

#!/bin/bash
echo $1
echo $2

这就像你要求的那样输出前两个参数。

您想使用第一个参数,然后将所有其余参数用作输入文件。所以像这样使用shift

#!/bin/bash
search=$1
shift

echo "$1"
echo "$@"

另请注意使用双引号。

在您的情况下,因为您希望搜索字符串和文件名以相同的顺序传递给grep,您甚至不需要shift

#!/bin/bash

grep -oHnR -e "$@"

(如果搜索字符串以-e开头,我添加了-


1
投票

当你打电话给剧本时,没有引用的*正受到globbing的影响。

使用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将*扩展到文件名列表,而第二种情况是将其传递给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

0
投票

您可能想要在bash调用中转义通配符:

bash test.bash TEST Logs/test\*

这样它就会被传递给grep作为*,否则shell会将它扩展到Logs目录中的每个文件,其名称以test开头。

或者,更改脚本以在命令行上允许多个文件:

#!/bin/bash
hold=$1
shift
grep -oHnR $hold $@
© www.soinside.com 2019 - 2024. All rights reserved.