awk asignar a múltiples variables a la vez

9

Estoy tratando de extraer dos valores numéricos de una cadena y asignarlos a variables usando awk( gawkes lo que estoy usando específicamente). Quiero extraer los números de versión mayor y menor de una cadena de versión tmux en awkvariables, por ejemplo:

  • entrada tmux 2.8:; maj == 2ymin == 8
  • entrada tmux 1.9a:; maj == 1ymin == 9
  • entrada tmux 2.10:; maj == 2ymin == 10

Suponiendo que mi entrada proviene de tmux -Vstdin, actualmente tengo lo siguiente:

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

Esto funciona, pero como muchos usuarios de tmux saben, usar if-shellen el .tmux.confarchivo (donde espero usar esto) puede conducir fácilmente a líneas realmente largas en el archivo de configuración, por lo que me pregunto si hay una manera de combinar estas dos variables asignaciones en una declaración para ahorrar espacio ... o cualquier otra forma de recoger estas dos variables de la entrada y ahorrar espacio.

Estoy pensando en algo como:

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

... algo así como en Python, pero esa sintaxis particular no existe en awk. ¿Hay algo más que sea posible?

Tenga en cuenta que la legibilidad no es realmente una preocupación, solo la longitud.

villapx
fuente

Respuestas:

9

Tenga en cuenta que gensubes una gawkextensión, no funcionará con ninguna otra awkimplementación. También tenga en cuenta que el +operador unario no fuerza la conversión numérica en todas las awkimplementaciones, el uso + 0es más portátil.

Aquí puedes hacer:

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

Si no le importa usar awkextensiones GNU , también puede hacer:

tmux -V | awk -v FPAT='[0-9]+' '{maj = $1; min = $2; print maj, min}'
Stéphane Chazelas
fuente
¡Gracias por las explicaciones adicionales sobre compatibilidad!
villapx
5

Puede dividir la versión en una matriz:

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

luego use en ver[1]lugar de maj, en ver[2]lugar de min.

Agregar a-zal separador elimina cualquier letra minúscula del número de versión. (Las otras soluciones son mejores aquí ya que extraen números explícitamente).

Stephen Kitt
fuente
3

Otro usuario publicó esta respuesta, y luego fue eliminada. Pensé que era útil:

Usando la split()función, divida la cadena de versión en una matriz ver, luego acceda ver[1]y en ver[2]lugar de majy min, respectivamente (o simplemente almacene los valores en esas variables):

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

La ventaja aquí es que split()no es una gawkextensión (aunque su cuarto argumento opcional sí lo sepses).

villapx
fuente
+1 pero ¿por qué usarlo /[.a-z]/como el tercer argumento (separación de campo) de la splitfunción de cadena, en lugar de solo "."?
Cbhihe
2
@Cbhihe ve la explicación de mi respuesta (que no eliminé ya que villapx cree que es útil, ¡gracias villapx!).
Stephen Kitt