特殊的管道 grep/head 行為

特殊的管道 grep/head 行為

我正在幫助網路管理員使用 perl 正規表示式自動操作 SAN 中的一些快照,我們的腳本執行以下操作:

varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1 | perl -pe 's/^tcp: \[\d*\] \d*\.\d*\.\d*\.\d*:\d*,\d* (iqn\..*\..*\..*:.*-.*-.*-.*-(.*-.*-\d{4}-\d{2}-\d{2}-\d{2}:\d{2}:\d{2}\.\d*\.\d*))$/$1/')

varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1 | perl -pe 's/^tcp: \[\d*\] \d*\.\d*\.\d*\.\d*:\d*,\d* (iqn\..*\..*\..*:.*-.*-.*-.*-(.*-.*-\d{4}-\d{2}-\d{2}-\d{2}:\d{2}:\d{2}\.\d*\.\d*))$/$2/')

快照的簽名中有兩個部分,一個嵌套在另一個中,我們使用捕獲組來捕獲名稱和需要執行的不同後續命令的名稱的一部分。我知道它一遍又一遍地運行相同的命令,並且可以稍後清理正則表達式,但基本上他們使用 perl 來輸出一個括號和另一個。

tcp: [32] 40.40.40.101:3260,1 iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1
tcp: [33] 40.40.40.101:3260,1 iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

想要捕捉 icsiadm 和 grep 的結果以獲得以下結果:

iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

我們遇到的問題是,有時通往第一行的管道會失敗:

head: cannot open '–n1' for reading: No such file or directory

當然,這似乎表明頭的標準輸入為空,因此它正在尋找檔案名稱。

但它沒有理由永遠是空的。

如果我們這樣做:

varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)
varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)

第二個將失敗,第二個變數將為空。

然而,如果我們反轉它們,那麼 varsnap1 將會失敗:

varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)
varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)

這很奇怪,我們不知道發生了什麼事。當我們從命令列運行 iscsiadm 命令時以及 grep 之後,每次運行它都會返回相同的內容。

是不是有什麼東西把管道弄亂了?

RedHat Enterprise Linux 上的 head 版本 5.97

答案1

雖然您的問題可能包含錯誤(長 utf8 破折號而不是正常的破折號):

$ head –n1
head: cannot open ‘–n1’ for reading: No such file or directory
$ head -n1 # ctrl-d
$ 

我認為這只是瀏覽器的問題,因為只有一次是這樣的。head無論如何,在需要時等待輸入。嘗試head -n1用以下其中一個替換:

sed -n 1p
awk 'NR==1 {print}' # yay, no potential dash problems

好的,還有很多方法可以做到這一點,但您也可以跳過該管道元素,只grep通過添加參數來告訴僅返回第一個匹配項-m 1。或消除兩個元素並告訴perl僅在第一個匹配行上進行操作。

相關內容