コマンド出力から2つの値を抽出する

コマンド出力から2つの値を抽出する

合成Wi-Fi情報を取得するには、スクリプトで次のコマンドを使用します。

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しかし、結果が同じであることを知っていても、同じ呼び出しを2回行うことは愚かなことのように感じます。また、出力をiw一時変数に保存することを避けたいと思います。

teeを使用して出力を両方のタスクiwに「コピー」してから結果をリンクするなど、私ができることはありますか?

ベストアンサー1

一時変数の使用には問題はありません。変数は、複数回使用されるデータを格納するために使用されます。

この場合、2つの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//'
)"

元のスクリプトとは1つの違いがあります。 SSIDと信号値は、出力に表示される順序で印刷されますiw。その順序に依存しない場合は、sedを使用するのが面倒である可能性があるため、awkを選択するツールになります。これにより、1行に出力を取得するのは簡単です。次のスクリプトは各設定の最後の値を出力します(iw1つだけ出力されるため、この場合は問題ありません)。すべて印刷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}
'

通常、コマンドの出力を2つの異なるフィルタに送信したい場合は、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//'

この方法の 1 つの制限は、プロセス置換コマンドが独自のサブシェルで実行されることです。ここでは変数を取得できず、その出力が他の出力と散在する方法を制御することもできません。

おすすめ記事