[英]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.