awk printステートメントをチェーンする方法は?


5

さて、ここに簡単な例を示します。3つの手順でホストのIPV4を分離します。

ip -br a  
lo               UNKNOWN        127.0.0.1/8 ::1/128 
eth0             DOWN           
wlan0            UP             192.168.0.101/24 fe80::9fcd:45fb:1e0f:a1cc/64 
ip -br a | awk '/wlan0/ {print $3}'  
192.168.0.101/24
ip -br a | awk '/wlan0/ {print $3}' | awk -F '/' '{print $1}'
192.168.0.101

awk(の出力を次のインスタンスにパイプする)の2番目のインスタンスを呼び出す代わりに; どのようにすべてを一度に行うことができますか?


言いたかったのは、質問はの出力を解析することではありませんip。質問を説明するのに役立つ簡単な例が必要でした。これが最初に思いついたものでした。実際の質問はタイトルにまとめられています。

とにかく、それが価値があるもののために(私はそれをチェックする必要がありますが、私はかなり確信しています); これは(最近の)過去に私がやったことです:

ip -br a s dev wlan0 | awk -F '[ /]*' '{print $3}'
192.168.0.101

回答:



2

フィールド区切りの定義を変更して、スペースと/

$ ip -br a | awk -F'[[:blank:]/]+' '/wlan0/{print $3}'
192.168.0.101

このオプション-F'[[:blank:]/]+'は、入力時にフィールド区切り文字として空白、タブ、またはスラッシュの任意の組み合わせを使用するようにawkに指示します。


これにより、ip例の正しい結果が得られます。しかし、OPは、それip単なる実例であると言っています。実際の質問は次のとおりです。1 awk '{print $3}' | awk -F '/' '{print $1}'つのawkコマンドでどのようにすればよいですか/。入力行の最初または2番目の(空白で区切られた)単語にが含まれている場合、この回答は失敗します。具体的には、その場合、最初の単語の3番目のサブフィールド、または2番目の単語の最初または2番目のサブフィールドを出力します。
Gマン

2

この場合、最も簡単な方法は、おそらく正規表現を使用して複数の区切り文字を設定することです。

ip -br a | awk -F '[\t /]*' '/wlan0/ {print$3}'

これにより、フィールド区切り文字が/、スペース、またはタブの文字列になり、3番目のフィールドが出力されます。

どんな行うには、任意のあなたが希望の2つのコマンドを、あなたはかなりの完全なawkプログラミング言語を習得する必要があります。私はそれに対してお勧めします-あなたはあなたの時間と関係があるより良いものがあると確信しています。


これにより、ip例の正しい結果が得られます。しかし、OPは、それip単なる実例であると言っています。実際の質問は次のとおりです。1 awk '{print $3}' | awk -F '/' '{print $1}'つのawkコマンドでどのようにすればよいですか/。入力行の最初または2番目の(空白で区切られた)単語にが含まれている場合、この回答は失敗します。具体的には、その場合、最初の単語の3番目のサブフィールド、または2番目の単語の最初または2番目のサブフィールドを出力します。
Gマン

@ G-Man私の実例は完全な解決策ではなく、この場合にうまくいくトリックに完全に同意します。しかし、それが私のポイントです-ステートメントを連鎖するための一般的な方法はありませんawk。すべてのステートメントに個別の「トリック」が必要です。したがって、「任意の 2つのコマンドを実行するには、完全なawkプログラミング言語を学ぶ必要があります。」
クリス

2

他の答えは根底にある問題を解決しますが、「awk印刷ステートメントを連鎖させるにはどうすればよいですか?」という質問には本当に答えません。

この種の問題に対する答えは、「あなたはしません」です。残りの言語を使用して、目的の結果が得られるまでソースを操作します。これが他の2つの答えです。print最終結果の出力にのみ使用します。

/wlan0//^wl/私の場合はWiFiの名前が異なるため)などの初期範囲パターンを指定すると、アクションであるコード内は{}、その文字列を含む入力行でのみ動作します。

それができたら、その入力行で必要なことは何でもできます。

ip -br a | \
awk '
/^wl/ {
  ip1 = $3
  gsub(/\/.*/, "", ip1)
  print ip1
}
'

このコードは、目的のフィールドを取得して変数に入れ、その変数の内容を編集してから印刷します。

他の答えはこれと同じことをより効率的に行いますが、これは他のステップを追加できるより一般的なケースを示しています。結果を保存して、後で別の入力行などで使用できるようにすることもできます。

実際に「プリントチェーン」のように見えるものについては、awkには、sprintf()入力を変数にフォーマットして印刷して、さらに処理する機能があります。

または、1行に複数のものを印刷する場合、コードはprintf()改行なしで複数のステートメントを使用して、最後まで1行ずつ出力行を作成できます。


これは、質問に対するこれまでのベストアンサーです。1 awk '{print $3}' | awk -F '/' '{print $1}'つのawkコマンドでどのように行いますか?しかし、これをどのように一般化できますawk '{print $3}' | awk -F '/' '{print $4}'か?たとえば、fox指定された入力を印刷するにはwlan0 foo/bar the/quick/brown/fox/jumps/over/the lazy/dog
G-マン

0

これはいくぶんStephen Rauchの答えJoeの答え精神にありますが、より良いものです:

awk '/wlan0/ {split($3, a, "/"); print a[1]}'

これは、3番目のフィールド($3)を取得split/て、区切り文字として使用します。コンポーネントは配列aに入り、サブフィールドの数が返されます。(このスニペットでは、戻り値を無視しています。)3番目のフィールドのa[1]最初の/区切りサブフィールドも同様です  。

これは、他の回答よりも簡単に一般化できます。たとえば、入力が

かつて真夜中のうんざりしていましたが、私は熟考し、弱くて疲れていましたが、
忘れられた伝承の古風で奇妙なボリュームがたくさんあります—
wlan0 foo / bar the / quick / brown / fox / jumps / over / the lazy / dog
うなずいて、うたた寝しそうになったとき、突然たたきがありました。
ある時点で、静かにラップしています。私の部屋のドアをラップしています。

その後、コマンド

awk '/wlan0/ {if (split($3, a, "/") < 4) print "There is no fourth subfield";
                                    else print "The fourth subfield is", a[4]}'

fox、戻り値をチェックしsplit て(少なくとも)4つのサブフィールドがあることを確認した後、3行目の3番目のフィールドの4番目のサブフィールド()を出力します。すなわち、これは

awk '/wlan0/ {print $3}' | awk -F '/' '{print $4}'

awkエラーチェック付きの単一コマンドで。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.