Linux

管道到我自己的腳本

  • May 7, 2015

我最近注意到來自 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在三個文件中搜尋: foodshoppinglist.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

對。

  1. 這是可笑的不切實際。
  2. 即使那失敗了
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 具有您想要的行為:

在此處輸入圖像描述

引用自:https://unix.stackexchange.com/questions/201689