Bash
從命令的輸出中提取兩個值
我在腳本中使用以下命令來獲取合成 wifi 資訊:
echo "$( iw dev wlp1s0 link | grep '^\s*SSID:\s' | sed -r 's/^\s*SSID:\s//' ) $( iw dev wlp1s0 link | grep '^\s*signal:\s' | sed -r 's/^\s*signal:\s//' )"
它有效,輸出如下:
MySSID -46 dBm
iw dev wlp1s0 link
但是,當我知道結果將相同時,兩次呼叫相同的呼叫感覺很愚蠢。另外,我想避免將輸出儲存iw
在臨時變數中。有什麼我可以做的,也許是使用
tee
,將輸出“複製”iw
到兩個工作,然後連接結果?
使用臨時變數並沒有錯:變數是用來儲存要多次使用的數據。
在這種情況下,您可以將兩個 grep/sed 呼叫組合成一個對 GNU grep、sed 或 awk 的呼叫。使用 sed 很容易:傳遞
-n
選項以僅輸出顯式列印的行,並列印進行替換的行。echo "$( iw dev wlp1s0 link | sed -nr -e 's/^\s*SSID:\s//p' -e 's/^\s*signal:\s//' )"
與您的原始腳本有一個不同之處:SSID 和信號值按照它們出現在輸出中的順序列印
iw
。如果您想獨立於該命令,則使用 sed 會很麻煩,因此 awk 將是首選工具。使用這種方法,在單行上獲得輸出同樣容易。以下腳本列印每個設置的最後一個值(iw
僅輸出一個,因此在這種特定情況下無關緊要);更改例如ssid = $0
以ssid = ssid " " $0
將它們全部列印出來。iw dev wlp1s0 link | awk ' $1=="SSID:" {sub(/[^:]*:[[:space:]]*/,""); ssid = $0} $1=="signal:" {sub(/[^:]*:[[:space:]]*/,""); signal = $0} END {print ssid, signal} '
一般來說,如果你想將命令的輸出發送到兩個不同的過濾器,你可以使用
tee
並傳遞一個程序替換。這是一個泛化管道的 bash 功能(來自 ksh93,也存在於 zsh 中,但不存在於普通 sh 中)。該tee
命令會看到一個文件名,該文件名指定連接到指定命令的管道。iw dev wlp1s0 link | tee >( grep '^\s*SSID:\s' | sed -r 's/^\s*SSID:\s//' ) | grep '^\s*signal:\s' | sed -r 's/^\s*signal:\s//'
這種方法的一個限制是程序替換中的命令在它自己的子shell 中執行。您無法從中獲取變數或控制其輸出如何與其他變數穿插。