awk przypisuje do wielu zmiennych jednocześnie

9

Próbuję wyciągnąć dwie wartości liczbowe z ciągu i przypisać je do zmiennych za pomocą awk( gawkwłaśnie tego używam). Chcę wyciągnąć główne i drobne numery wersji z łańcucha wersji tmux do awkzmiennych, np .:

  • wkład tmux 2.8:; maj == 2imin == 8
  • wkład tmux 1.9a:; maj == 1imin == 9
  • wkład tmux 2.10:; maj == 2imin == 10

Zakładając, że mój wkład pochodzi ze tmux -Vstandardowego wejścia, obecnie mam następujące elementy:

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

Działa to, ale jak wie wielu użytkowników tmux, użycie if-shellw .tmux.confpliku (gdzie mam nadzieję użyć tych rzeczy) może łatwo prowadzić do naprawdę długich linii w pliku konfiguracyjnym, więc zastanawiam się, czy istnieje sposób na połączenie tych dwóch zmiennych przypisania do jednej instrukcji, aby zaoszczędzić miejsce ... lub w jakikolwiek inny sposób uzyskać te dwie zmienne z danych wejściowych i zaoszczędzić miejsce.

Mam na myśli coś takiego:

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

... jak w Pythonie, ale ta szczególna składnia nie istnieje awk. Czy jest coś jeszcze, co jest możliwe?

Pamiętaj, że czytelność nie jest tak naprawdę problemem, tylko długość.

villapx
źródło

Odpowiedzi:

9

Pamiętaj, że gensubjest to gawkrozszerzenie, nie będzie działać z żadną inną awkimplementacją. Zauważ też, że +operator jednoargumentowy nie wymusza konwersji numerycznej we wszystkich awkimplementacjach, użycie + 0jest bardziej przenośne.

Tutaj możesz zrobić:

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

Jeśli nie masz nic przeciwko korzystaniu z awkrozszerzeń GNU , możesz także:

tmux -V | awk -v FPAT='[0-9]+' '{maj = $1; min = $2; print maj, min}'
Stéphane Chazelas
źródło
Dziękujemy za dodatkowe wyjaśnienia dotyczące zgodności!
villapx
5

Możesz podzielić wersję na tablicę:

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

następnie użyj ver[1]zamiast maj, ver[2]zamiast min.

Dodanie a-zdo separatora usuwa wszystkie małe litery z numeru wersji. (Inne rozwiązania są tutaj lepsze, ponieważ wyraźnie wydobywają liczby).

Stephen Kitt
źródło
3

Inny użytkownik opublikował tę odpowiedź, która została później usunięta. Myślałem, że to się przyda:

Korzystanie z split()funkcji, podzielić ciąg wersji na tablicę ver, a następnie dostęp ver[1]i ver[2]zamiast maji min, odpowiednio, (lub po prostu przechowywać wartości w tych zmiennych):

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

Plusem jest to, że split()nie jest to gawkrozszerzenie (choć opcjonalny czwarty argument sepsto).

villapx
źródło
+1, ale po co używać /[.a-z]/trzeciego argumentu (rozdzielającego pola) splitfunkcji łańcuchowej zamiast po prostu "."?
Cbhihe
2
@Chihi widzi wyjaśnienie mojej odpowiedzi (którą usunąłem, ponieważ villapx uważa ją za przydatną, dzięki villapx!).
Stephen Kitt