管道到我自己的腳本
我最近注意到來自 grep 的這條消息
"grep: warning: GREP_OPTIONS is deprecated; please use an alias or script"
我收到此警告是因為 –color=always 在我的 .bashrc 文件中定義。AFAIK 別名是不切實際的,因為我希望它在管道上工作。例如,
echo "a b c" |grep b
應突出顯示 b。由於別名不起作用,因此提供的另一個選項是製作腳本。但是如何讓腳本接受來自管道的輸入?在這種情況下,我希望腳本附加 –color=always。
編輯:畢竟別名確實有效……製作腳本也是如此。我不知道我在使用別名方法時做錯了什麼。但是,在製作腳本時,一定要包含 $1 作為輸入參數。
對於其他想知道如何通過管道傳輸到您自己的腳本的人,在此範例中,它通過執行以下操作對我有用:
首先將腳本放在路徑中的某個位置,以便其可執行,例如
# ~/.bin/testgrep grep --color=always $1
現在使腳本可執行,例如
chmod +x ~/.bin/testgrep
現在它應該工作了!
grep
(即/bin/grep
)如果在沒有文件名參數的情況下呼叫它,將從標準輸入中讀取。grep
因此,編寫一個使用來自標準輸入的輸入執行的腳本很簡單——只需grep
在沒有文件名參數的情況下呼叫即可。但grep
必須(至少)給出一個PATTERN參數(或等效參數)。一種非常不靈活的方法是在你的 grep 腳本中硬編碼一個搜尋字元串(模式),這在現實生活中不太可能非常有用。例如,#!/bin/sh grep --color=always cat
可以在上下文中使用
ps | mygrep
可能不多。稍微靈活一點的腳本可能會使用環境變數作為搜尋字元串:
#!/bin/sh grep --color=always $USER
可以在上下文中使用
ps -ef | mygrep
可能不多。唯一合理、現實、穩健的解決方案是允許腳本使用者提供搜尋字元串作為命令行參數:
#!/bin/sh grep --color=always $1
可以在上下文中使用
dmesg | mygrep TCP
並且實際上可能相當有用。
好吧,也許我應該說有點用處。這很快就會崩潰,因為您可能需要多個參數來指定搜尋參數:
mygrep -i tcp *不區分大小寫的搜尋;查找*tcp *、* TCP *、* Tcp*等* mygrep -v bash *查找**除***bash之外的所有內容*。* mygrep -e cat -e dog *查找包含*cat***或***dog的每一行*。* mygrep -f wordlist *搜尋字元串在文件中。*
所以我們腳本的第二稿可能是:
#!/bin/sh grep --color=always $1 $2 $3 $4 $5 $6 $7 $8 $9
它可以處理上述任何範例。作為額外的獎勵,它不需要用於讀取標準輸入;我們可以說
mygrep -i path .bashrc
它會執行
grep --color=always -i path .bashrc
但我們還沒有完成!考慮
mygrep "cat food" "shopping list.txt"
這將執行
grep --color=always cat food shopping list.txt
它將(嘗試)
cat
在三個文件中搜尋:food
、shopping
和list.txt
. 好的,我們可以這樣說#!/bin/sh grep --color=always "$1" "$2"
但
#!/bin/sh grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"
不是一個好的答案;它會轉
mygrep "cat food" "shopping list.txt"
進入
grep --color=always "cat food" "shopping list.txt" "" "" "" "" "" "" ""
這會做你想做的事,但也會發出七條錯誤消息。
那麼,該做什麼,該做什麼呢?等一下; 我的衣櫃裡有一把大錘:
#!/bin/sh if [ "$1" = "" ] then printf "%s\n" "error: mygrep must be run with at least one argument." elif [ "$2" = "" ] then grep --color=always "$1" elif [ "$3" = "" ] then grep --color=always "$1" "$2" elif [ "$4" = "" ] then grep --color=always "$1" "$2" "$3" elif [ "$5" = "" ] then grep --color=always "$1" "$2" "$3" "$4" elif [ "$6" = "" ] then grep --color=always "$1" "$2" "$3" "$4" "$5" elif [ "$7" = "" ] then grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" elif [ "$8" = "" ] then grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" elif [ "$9" = "" ] then grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" else grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" fi
對。
- 這是可笑的不切實際。
- 即使那失敗了
mygrep -e cat -e dog -e fish file1 file2 file3 file4
因為它有超過九個參數!而且,雖然這種情況看起來不太可能,但同樣的問題發生在
mygrep bird *
如果目前目錄中有超過八個(非隱藏)文件。
那麼,該做什麼,該做什麼呢?
TL; 博士
如果您查看特殊參數 下的bash(1),您會看到它擴展到位置參數列表,從一個開始。當擴展出現在雙引號內時,每個參數都擴展為一個單獨的單詞。也就是說,等價於……(在上面的長腳本中實現,但不限於前九個)。因此,編寫腳本來包裝(即,充目前端)某些命令(就像別名一樣)的方法是
$@``"$@"``"$1"
"$2"
#!/bin/sh grep --color=always "$@"
別名將起作用。我
grep
別名為grep --color=auto
:% which grep grep: aliased to grep --color=auto
並且管道到 grep 具有您想要的行為: