awk mehreren Variablen gleichzeitig zuweisen

9

Ich versuche, zwei numerische Werte aus einer Zeichenfolge zu ziehen und sie mithilfe von Variablen zuzuweisen awk( gawkwas ich speziell verwende). Ich möchte die Haupt- und Nebenversionsnummern aus einer tmux-Versionszeichenfolge in awkVariablen ziehen, z.

  • Eingabe : tmux 2.8; maj == 2undmin == 8
  • Eingabe : tmux 1.9a; maj == 1undmin == 9
  • Eingabe : tmux 2.10; maj == 2undmin == 10

Angenommen, meine Eingabe stammt von tmux -Vstdin, habe ich derzeit Folgendes:

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

Dies funktioniert, aber wie viele Benutzer von tmux wissen, kann die Verwendung if-shellin der .tmux.confDatei (wo ich dieses Zeug verwenden möchte ) leicht zu sehr langen Zeilen in der Konfigurationsdatei führen. Daher frage ich mich, ob es eine Möglichkeit gibt, diese beiden Variablen zu kombinieren Zuweisungen in eine Anweisung, um Platz zu sparen ... oder eine andere Möglichkeit, diese beiden Variablen aus der Eingabe zu entnehmen und Platz zu sparen.

Ich denke an etwas wie:

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

... ähnlich wie in Python, aber diese spezielle Syntax existiert in nicht awk. Gibt es noch etwas, das möglich ist?

Beachten Sie, dass die Lesbarkeit nicht wirklich ein Problem ist, sondern nur die Länge.

villapx
quelle

Antworten:

9

Beachten Sie, dass dies gensubeine gawkErweiterung ist und mit keiner anderen awkImplementierung funktioniert . Beachten Sie auch, dass der +unäre Operator nicht in allen awkImplementierungen die numerische Konvertierung + 0erzwingt. Die Verwendung ist portabler.

Hier könnten Sie tun:

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

Wenn es Ihnen nichts ausmacht, GNU- awkErweiterungen zu verwenden, können Sie auch Folgendes tun:

tmux -V | awk -v FPAT='[0-9]+' '{maj = $1; min = $2; print maj, min}'
Stéphane Chazelas
quelle
Vielen Dank für die zusätzlichen Erklärungen zur Kompatibilität!
Villapx
13

Da Sie GNU awk verwenden, können Sie die 3-Argumente-Form von verwenden match(), um mehrere Erfassungsgruppen zu speichern:

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

Glenn Jackman
quelle
5

Sie können die Version in ein Array aufteilen:

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

verwenden Sie dann ver[1]statt maj, ver[2]statt min.

Durch Hinzufügen a-zzum Trennzeichen werden Kleinbuchstaben aus der Versionsnummer entfernt. (Die anderen Lösungen sind hier besser, da sie explizit Zahlen extrahieren.)

Stephen Kitt
quelle
3

Ein anderer Benutzer hat diese Antwort gepostet und sie wurde später gelöscht. Ich fand es nützlich:

Mit Hilfe der split()Funktion, teilen Sie die Versionszeichenfolge in ein Array ver, dann Zugang ver[1]und ver[2]statt majund minjeweils (oder einfach speichern die Werte in diesen Variablen):

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

Das Plus hier ist, dass split()es sich nicht um eine gawkErweiterung handelt (obwohl das optionale vierte Argument sepslautet).

villapx
quelle
+1, aber warum /[.a-z]/als drittes Argument (Feldtrennung) der splitZeichenfolgenfunktion verwenden, anstatt nur "."?
Cbhihe
2
@Cbhihe siehe die Erklärung auf meiner Antwort (die ich nicht gelöscht habe, da villapx es für nützlich hält, danke villapx!).
Stephen Kitt