2012-08-23 25 views
4

所以,命令:慶典/ SH -c無法與多個管道工作

dmesg | grep 'Attached SCSI disk' | awk '{ print $5}' 

當從外殼直接執行,就像它應該輸出:

[sdb]
[sdc]
[sda]

但是,當我與啓動它:

sh -c "dmesg | grep 'Attached SCSI disk' | awk '{ print $5}'" 
# or 
bash -c "dmesg | grep 'Attached SCSI disk' | awk '{ print $5}'" 

我得到:

[ 2.460353] sd 1:0:0:0: [sdb] Attached SCSI disk
[ 2.461348] sd 2:0:0:0: [sdc] Attached SCSI disk
[ 2.464181] sd 0:0:0:0: [sda] Attached SCSI disk

這清楚地表明,過去的管還沒有執行。

我在做什麼錯?

+7

另外,反模式'grep x | awk'{stuff}''通常可以簡化爲'awk'/ x/{stuff}' – tripleee

回答

13

您的$5正在評估太早。將其更改爲\$5

如果你有echo更換bash,你會看到$5是由空字符串替換:

% echo "dmesg | grep 'Attached SCSI disk' | awk '{ print $5}'" 
dmesg | grep 'Attached SCSI disk' | awk '{ print }' 

所以,當bash評估命令時,awk將要打印的整條生產線,不是第五個領域。

當你逃離美元符號(用反斜槓預prending),變量$5被保留:

% echo "dmesg | grep 'Attached SCSI disk' | awk '{ print \$5}'" 
dmesg | grep 'Attached SCSI disk' | awk '{ print $5}' 
+0

好的,修正了它,有沒有解釋爲什麼? – jolt

+5

整個字符串在傳遞給'sh'或'bash'之前都要經過參數擴展。因爲它是用雙引號引起來的,所以'$ 5'被解釋爲一個shell位置參數。 (單引號不能保護它;它們只是字符串中的字符。) – chepner

+5

另外,您可以簡化爲:'dmesg | awk'/附加的SCSI磁盤/ {print $ 5}'' – mpe

0

還有就是$1在他們使用的shell和awk和解釋之間的衝突, $2,...

在所有伯恩後代(灰,慶典,破折號,ksh93的,zsh的),這些都表明編號的參數作爲命令行上傳遞,而$0被替換爲當前運行的腳本的名稱或交互式shell的名稱。

awk$1$2,...參照當前記錄,即當前輸入線的第一,第二等,詞的到相應字段$0總是指整個記錄,包括任何字段分隔符。

當從shell(腳本)調用awk時,您必須確保awk腳本已正確引用。爲了防止shell插入,請將awk代碼放在單引號內。