awk menetapkan beberapa variabel sekaligus


9

Saya mencoba menarik dua nilai numerik dari string dan menetapkannya ke variabel menggunakan awk( gawkadalah apa yang saya gunakan khusus). Saya ingin menarik nomor versi utama dan kecil dari string versi tmux ke dalam awkvariabel, misalnya:

  • masukan tmux 2.8:; maj == 2danmin == 8
  • masukan tmux 1.9a:; maj == 1danmin == 9
  • masukan tmux 2.10:; maj == 2danmin == 10

Dengan asumsi input saya berasal dari tmux -Vpada stdin, saat ini saya memiliki yang berikut:

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

Ini berfungsi, tetapi karena banyak pengguna tmux tahu, menggunakan if-shelldalam .tmux.conffile (di mana saya berharap untuk menggunakan hal ini) dapat dengan mudah mengarah ke garis yang sangat panjang dalam file konfigurasi, jadi saya bertanya-tanya apakah ada cara untuk menggabungkan kedua variabel ini tugas menjadi satu pernyataan untuk menghemat ruang ... atau cara lain untuk mendapatkan dua variabel ini dari input dan menghemat ruang.

Saya sedang memikirkan sesuatu seperti:

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

... seperti di Python, tetapi sintaks tertentu tidak ada di awk. Apakah ada hal lain yang mungkin?

Perhatikan bahwa keterbacaan sebenarnya bukan masalah, hanya panjang.

Jawaban:


9

Perhatikan bahwa gensubini adalah gawkekstensi, itu tidak akan berfungsi dengan awkimplementasi lainnya . Juga perhatikan bahwa +operator unary tidak memaksa konversi numerik di semua awkimplementasi, menggunakan + 0lebih portabel.

Di sini Anda dapat melakukannya:

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

Jika Anda tidak keberatan menggunakan awkekstensi GNU , Anda juga bisa melakukan:

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

Terima kasih atas penjelasan tambahan tentang kompatibilitas!
villapx


5

Anda dapat membagi versi menjadi array:

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

lalu gunakan ver[1]sebagai ganti maj, ver[2]alih-alih min.

Menambahkan a-zke pemisah menghapus huruf kecil apa pun dari nomor versi. (Solusi lain lebih baik di sini karena mereka secara eksplisit mengekstraksi angka.)


3

Pengguna lain memposting jawaban ini, dan kemudian dihapus. Saya pikir itu berguna:

Dengan menggunakan split()fungsi ini, pisahkan string versi ke dalam array ver, lalu akses ver[1]dan ver[2]alih - alih majdan minmasing-masing (atau cukup simpan nilai dalam variabel tersebut):

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

Nilai tambah di sini adalah bahwa split()itu bukan gawkekstensi (meskipun argumen opsional keempatnya sepsadalah).


+1 tetapi mengapa digunakan /[.a-z]/sebagai argumen (pemisahan bidang) ketiga dari splitfungsi string, bukan hanya "."?
Cbhihe

2
@Cbhihe melihat penjelasan pada jawaban saya (yang saya hapus karena villapx menganggap itu berguna, terima kasih villapx!).
Stephen Kitt
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.