awk attribuer à plusieurs variables à la fois

9

J'essaie de tirer deux valeurs numériques d'une chaîne et de les affecter à des variables à l'aide awk( gawkc'est ce que j'utilise spécifiquement). Je veux extraire les numéros de version majeurs et mineurs d'une chaîne de version tmux dans des awkvariables, par exemple:

  • entrée tmux 2.8:; maj == 2etmin == 8
  • entrée tmux 1.9a:; maj == 1etmin == 9
  • entrée tmux 2.10:; maj == 2etmin == 10

En supposant que mon entrée provient de tmux -Vstdin, j'ai actuellement les éléments suivants:

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

Cela fonctionne, mais comme de nombreux utilisateurs de tmux le savent, l'utilisation if-shelldans le .tmux.conffichier (où j'espère utiliser ce genre de choses) peut facilement conduire à de très longues lignes dans le fichier de configuration, donc je me demande s'il existe un moyen de combiner ces deux variables affectations en une seule instruction pour économiser de l'espace ... ou de toute autre manière pour glaner ces deux variables de l'entrée et économiser de l'espace.

Je pense à quelque chose comme:

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

... un peu comme en Python, mais cette syntaxe particulière n'existe pas dans awk. Y a-t-il autre chose possible?

Notez que la lisibilité n'est pas vraiment un problème, juste la longueur.

villapx
la source

Réponses:

9

Notez qu'il gensubs'agit d'une gawkextension, elle ne fonctionnera avec aucune autre awkimplémentation. Notez également que l' +opérateur unaire ne force pas la conversion numérique dans toutes les awkimplémentations, l'utilisation + 0est plus portable.

Ici, vous pourriez faire:

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

Si cela ne vous dérange pas d'utiliser des awkextensions GNU , vous pouvez également faire:

tmux -V | awk -v FPAT='[0-9]+' '{maj = $1; min = $2; print maj, min}'
Stéphane Chazelas
la source
Merci pour les explications supplémentaires sur la compatibilité!
villapx
5

Vous pouvez diviser la version en un tableau:

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

puis utilisez ver[1]au lieu de maj, ver[2]au lieu de min.

L'ajout a-zau séparateur supprime toute lettre minuscule du numéro de version. (Les autres solutions sont meilleures ici car elles extraient explicitement des nombres.)

Stephen Kitt
la source
3

Un autre utilisateur a publié cette réponse, qui a été supprimée par la suite. J'ai pensé que c'était utile:

À l'aide de la split()fonction, divisez la chaîne de version en un tableau ver, puis accédez à ver[1]et ver[2]plutôt qu'à majet min, respectivement (ou stockez simplement les valeurs dans ces variables):

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

Le plus ici est que ce split()n'est pas une gawkextension (bien que son quatrième argument facultatif sepssoit).

villapx
la source
+1 mais pourquoi utiliser /[.a-z]/comme troisième argument (séparation de champs) de la splitfonction chaîne, au lieu de juste "."?
Cbhihe
2
@Cbhihe voir l'explication sur ma réponse (que j'ai annulée car villapx pense que c'est utile, merci villapx!).
Stephen Kitt