web-dev-qa-db-ja.com

awkは一度に複数の変数に割り当てます

文字列から2つの数値を取得し、awkを使用して変数に割り当てようとしています(gawkは特に使用しているものです)。 tmuxのバージョン文字列からメジャーバージョン番号とマイナーバージョン番号をawk変数に取り出したいのですが、例:

  • 入力:tmux 2.8; maj == 2およびmin == 8
  • 入力:tmux 1.9a; maj == 1およびmin == 9
  • 入力:tmux 2.10; maj == 2およびmin == 10

私の入力がtmux -V stdinで、私は現在次のものを持っています:

tmux -V | awk '{
                  maj = +gensub(/([0-9]+)\..*/, "\\1", "g", $2);
                  min = +gensub(/.*\.([0-9]+).*/, "\\1", "g", $2);
                  # ...do something with maj and min...
               }'

これは機能しますが、tmuxの多くのユーザーが知っているように、if-Shell の中に .tmux.confファイル(このようなものを使用したい場合)は、設定ファイルでreally長い行に簡単につながる可能性があるため、これらの2つの変数の割り当てを1つのステートメントに結合する方法があるかどうか疑問に思っています。スペースを節約...または、入力からこれら2つの変数を収集してスペースを節約するその他の方法。

私は次のようなことを考えています:

awk '{ maj, min = +gensub(/([0-9]+)\.([0-9]+).*/, "\\1 \\2", "g", $2); }'

... Pythonのようなものですが、その特定の構文はawkには存在しません。他に可能なことはありますか?

読みやすさは本当に問題ではなく、長さだけに注意してください。

9
villapx

gensubgawk拡張機能であり、他のawk実装では機能しないことに注意してください。また、+単項演算子は、すべてのawk実装で数値変換を強制しないため、+ 0の方が移植性が高いことに注意してください。

ここであなたがすることができます:

tmux -V | awk -F '[ .]' '{maj = $2+0; min = $3+0; print maj, min}'

GNU awk拡張機能を使用してもかまわない場合は、次のようにすることもできます。

tmux -V | awk -v FPAT='[0-9]+' '{maj = $1; min = $2; print maj, min}'
9

GNU awkを使用しているため、match()の3引数形式を使用して、複数のキャプチャグループを格納できます。

awk '
    match($0, /([0-9]+)\.([0-9]+)/, m) {maj=m[1]; min=m[2]; print maj, min}
' <<END
tmux 2.8
tmux 1.9a
tmux 2.10
END
2 8
1 9
2 10

https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html

13
glenn jackman

バージョンを配列に分割できます:

awk '{ split($2, ver, /[.a-z]/) }'

次に、majの代わりにver[1]を使用し、minの代わりにver[2]を使用します。

セパレータにa-zを追加すると、バージョン番号から小文字が削除されます。 (他のソリューションは明示的に数値を抽出するため、ここではより優れています。)

5
Stephen Kitt

別のユーザーがこの回答を投稿しましたが、後で削除されました。私はそれが便利だと思いました:

split()関数を使用して、バージョン文字列を配列verに分割し、それぞれmajおよびminではなくver[1]およびver[2]にアクセスします(または単にこれらの変数に値を格納します):

tmux -V | awk '{ split($2, ver, /[.a-z]/); print ver[1], ver[2] }'

ここでのプラスは、split()gawk拡張ではないことです(オプションの4番目の引数sepsはそうです)。

3
villapx