awk gán cho nhiều biến cùng một lúc


9

Tôi đang cố gắng kéo hai giá trị số ra khỏi một chuỗi và gán chúng cho các biến bằng cách sử dụng awk(đó gawklà những gì tôi đang sử dụng cụ thể). Tôi muốn kéo các số phiên bản chính và phụ ra khỏi chuỗi phiên bản tmux thành awkcác biến, ví dụ:

  • đầu vào : tmux 2.8; maj == 2min == 8
  • đầu vào : tmux 1.9a; maj == 1min == 9
  • đầu vào : tmux 2.10; maj == 2min == 10

Giả sử đầu vào của tôi đến từ tmux -Vtrên stdin, tôi hiện có những điều sau đây:

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

Điều này hoạt động, nhưng như nhiều người dùng tmux biết, sử dụng if-shelltrong .tmux.conftệp (nơi tôi hy vọng sử dụng công cụ này) có thể dễ dàng dẫn đến các dòng thực sự dài trong tệp cấu hình, vì vậy tôi tự hỏi liệu có cách nào để kết hợp hai biến này không gán vào một câu lệnh để tiết kiệm không gian ... hoặc bất kỳ cách nào khác để thu thập hai biến này từ đầu vào và tiết kiệm không gian.

Tôi đang nghĩ về một cái gì đó như:

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

... giống như trong Python, nhưng cú pháp cụ thể đó không tồn tại awk. Có điều gì khác có thể không?

Lưu ý rằng khả năng đọc không thực sự là một mối quan tâm, chỉ là độ dài.

Câu trả lời:


9

Lưu ý rằng đó gensublà một gawkphần mở rộng, nó sẽ không hoạt động với bất kỳ awktriển khai nào khác . Cũng lưu ý rằng +toán tử đơn nguyên không bắt buộc chuyển đổi số trong tất cả các awktriển khai, sử dụng + 0dễ mang theo hơn.

Ở đây bạn có thể làm:

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

Nếu bạn không phiền khi sử dụng các awkphần mở rộng GNU , bạn cũng có thể làm:

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

Cảm ơn đã giải thích thêm về khả năng tương thích!
Villapx


5

Bạn có thể chia phiên bản thành một mảng:

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

sau đó sử dụng ver[1]thay vì maj, ver[2]thay vì min.

Thêm a-zvào dấu phân cách sẽ xóa mọi chữ cái viết thường khỏi số phiên bản. (Các giải pháp khác tốt hơn ở đây vì chúng trích xuất số rõ ràng.)


3

Một người dùng khác đã đăng câu trả lời này và sau đó nó đã bị xóa. Tôi nghĩ rằng nó hữu ích:

Sử dụng split()hàm, chia chuỗi phiên bản thành một mảng ver, sau đó truy cập ver[1]ver[2]thay vì majmintương ứng (hoặc đơn giản là lưu trữ các giá trị trong các biến đó):

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

Điểm cộng ở đây split()không phải là một gawkphần mở rộng (mặc dù đối số thứ tư tùy chọn của nó sepslà).


+1 nhưng tại sao lại sử dụng /[.a-z]/làm đối số thứ ba (tách trường) của splithàm chuỗi, thay vì chỉ "."?
Cbhihe

2
@Cbhihe xem phần giải thích về câu trả lời của tôi (điều mà tôi đã hoàn tác vì Villapx nghĩ rằng nó hữu ích, cảm ơn Villapx!).
Stephen Kitt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.