2012-09-08 30 views
1

我經常發現自己做這樣的事情很多:如何將bash函數的參數擴展爲管道命令鏈?

something | grep cat | grep bat | grep rat 

當所有我記得是那三個字一定是什麼地方發生,以某種順序,在something輸出......現在,我可以做這樣的事情:

something | grep '.*cat.*bat.*rat.*' 

但這意味着排序(蝙蝠出現在貓後)。因此,我想添加一個bash功能我的環境下調用mgrep這將打開的:

mgrep cat bat rat 

grep cat | grep bat | grep rat 

,但我不太清楚如何做到這一點(或者是否存在是另一種選擇?)。一個想法是用於遍歷像這樣的參數:

while (($#)); do 
    grep $1 some_thing > some_thing 
    shift 
done 
cat some_thing 

其中SOME_THING可能是當一個人確實在bash >(cmd),但我不知道一些FIFO等。如何繼續?

+0

這可能會有所幫助:http://stackoverflow.com/questions/941338/ shell-script-how-to-pass-command-line-arguments-to-unix-alias – Levon

+0

將整個管道生成爲一個字符串,並用'eval'執行它 – alexis

+0

是的,我想到了一個bash函數,謝謝亞歷克西斯,這是一個好主意,讓我嘗試一下。 –

回答

2

我相信你可能通過在每一步重定向標準輸入一次生成管道一個命令。但它更簡單和更清潔的生成您的管道作爲一個字符串,並與EVAL執行它,就像這樣:

CMD="grep '$1' " # consume the first argument 
shift 

for arg in "[email protected]" # Add the rest in a pipeline 
do 
    CMD="$CMD | grep '$arg'" 
done 
eval $CMD 

,這將產生裏grep的管道總是從標準輸入讀取,在你的模型。需要注意的是它保護在報價參數空間,使其正常工作,如果你寫:

mgrep 'the cat' 'the bat' 'the rat' 
+0

以下是我所做的,但感謝您的想法! –

2

感謝亞歷克西斯,這就是我所做的:

function mgrep() #grep multiple keywords 
{ 
    CMD='' 
    while (($#)); do 
     CMD="$CMD grep \"$1\" | " 
     shift 
    done 
    eval ${CMD%| } 
} 
+0

不錯,我不知道'$ {X%}'的語法。但考慮像我一樣引用'$ 1'--遲早你會希望在搜索中包含一個shell元字符,或者搜索一個短語,並且你的函數將會中斷。當它非常簡單時,編寫健壯的代碼會更好! – alexis

+0

哎呀,很好的電話。引。 –

1

你可以寫一個遞歸函數;我對基本案例不滿意,但我想不出更好的案例。這似乎是一種浪費需要調用cat只是標準輸入傳遞到標準輸出和while循環是有點不雅:

mgrep() { 
    local e=$1; 
    # shift && grep "$e" | mgrep "[email protected]" || while read -r; do echo "$REPLY"; done 
    shift && grep "$e" | mgrep "[email protected]" || cat 

    # Maybe? 
    # shift && grep "$e" | mgrep "[email protected]" || echo "$(</dev/stdin)" 
} 
+0

我喜歡這個!聰明。如何/爲什麼終止? –

+0

啊,好問題。如果其隱含的參數1大於位置參數的數量,則「shift」具有非零的退出。在這種情況下,調用'cat'而不是遞歸'grep' /'mgrep'管道。 – chepner