GNU/Linux >> Tutoriales Linux >  >> Linux

Separador de campo predeterminado para awk

Echemos un vistazo a la página del manual de GNU awk:

FS — El separador de campo de entrada, un espacio por defecto. Ver Campos , arriba.

A los Campos sección!

A medida que se lee cada registro de entrada, gawk divide el registro en campos, usando el valor de FS variable como separador de campo. Si FS es un solo carácter, los campos están separados por ese carácter. Si FS es la cadena nula, entonces cada carácter individual se convierte en un campo separado. De lo contrario, FS se espera que sea una expresión regular completa. En el caso especial de que FS es un solo espacio, los campos están separados por espacios y/o tabulaciones y/o saltos de línea.


He aquí un resumen pragmático que se aplica a todas las principales implementaciones de Awk :

  • GNU Awk (gawk ) - el awk predeterminado en algunos distribuciones de Linux
  • Mawk (mawk ) - el awk predeterminado en algunos Distribuciones de Linux (por ejemplo, versiones anteriores de Ubuntu)
  • BWK Awk:el awk predeterminado en plataformas similares a BSD, incluido macOS

Versiones recientes de todas estas implementaciones siguen el estándar POSIX con respecto al campo separadores (pero no registrar separadores).

Glosario:

  • RS es el entrada-registro separador , que describe cómo se divide la entrada en registros :

    • El valor predeterminado exigido por POSIX es una nueva línea , también conocido como \n abajo; es decir, la entrada se divide en líneas por defecto .
    • En awk línea de comando de, RS se puede especificar como -v RS=<sep> .
    • POSIX restringe RS a un literal, de un solo carácter valor, pero GNU Awk y Mawk admiten multi-character valores que pueden ser expresiones regulares extendidas (BWK Awk no apoya eso).
  • FS es el campo de entrada separador , que describe cómo cada registro se divide en campos ; puede ser una expresión regular extendida .

    • En awk línea de comando de, FS se puede especificar como -F <sep> (o -v FS=<sep> ).
    • El valor predeterminado exigido por POSIX es formalmente un espacio (0x20 ), pero ese espacio no es literalmente interpretado como el (único) separador, pero tiene un significado especial ; ver más abajo.

Por defecto :

  • cualquier ejecución de espacios y/o pestañas y/o nuevas líneas se trata como un separador de campo
  • con ejecuciones iniciales y finales ignoradas .

Tenga en cuenta que con el separador de registro de entrada predeterminado (RS ), \n , nuevas líneas normalmente no ingrese la imagen como separadores de campo , porque ningún registro sí mismo contiene \n en ese caso.

Nuevas líneas como separadores de campo hacer entra en juego , sin embargo:

  • Cuando RS se establece en un valor que da como resultado registros mismos que contiene \n instancias (como cuando RS se establece en la cadena vacía; ver más abajo).
  • Generalmente , cuando el split() La función se utiliza para dividir una cadena en elementos de matriz sin un argumento separador de campo explícito.
    • Aunque los registros de entrada no contendrá \n instancias en caso de que el RS predeterminado está en vigor, el split() función cuando se invoca sin un argumento separador de campo explícito en una cadena de varias líneas de una fuente diferente (por ejemplo, una variable pasada a través del -v opción o como un pseudo-nombre de archivo) siempre trata \n como separador de campos.

Consideraciones importantes NO predeterminadas :

  • Asignación del vacío cadena a RS tiene un significado especial :lee la entrada en modo párrafo , lo que significa que la entrada se divide en registros por ejecuciones de líneas no vacías , con ejecuciones iniciales y finales de líneas vacías ignoradas .

  • Cuando asignas algo otro que un literal espacio para FS , la interpretación de FS cambia fundamentalmente :

    • Un sencillo carácter o cada carácter de un conjunto de caracteres especificado es reconocida individualmente como separador de campos - no corre de él, como con el valor predeterminado.
      • Por ejemplo, configurar FS a [ ] - a pesar de que efectivamente equivale a un solo espacio - hace que cada individuo instancia de espacio en cada registro para ser tratado como un separador de campo.
      • Para reconocer carreras , el cuantificador de expresiones regulares (símbolo de duplicación) + debe ser usado; por ejemplo, [\t]+ reconocería carreras de pestañas como un solo separador.
    • Principal y posterior los separadores NO se ignoran y, en su lugar, separe vacío campos.
    • Configuración FS a la cadena vacía significa que cada carácter de un registro es su propio campo .
  • Según lo dispuesto por POSIX, si RS se establece en la cadena vacía (modo párrafo), nuevas líneas (\n ) son también separadores de campo considerados , independientemente del valor de FS .

  • Con -P en vigor y RS establecido en la cadena vacía , \n es todavía tratado como un separador de campo:
    gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
  • Con -P en vigor y un no vacío RS , \n NO se trata como un separador de campo; este es el comportamiento obsoleto:
    gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
    Se acerca una solución , según los mantenedores de GNU Awk; esperarlo en la versión 4.2 (No se especifica plazo).
    (Sugerencia para @JohnKugelman y @EdMorton por su ayuda).

'[ ]+' funciona para mí. Ejecute awk -W version para obtener la versión awk. El mio es GNU Awk 4.0.2 .

# cat a.txt
tcp        0      0 10.192.25.199:65002     0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:26895         0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:18422           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 10.192.25.199:8888      0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:50010           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:50075           0.0.0.0:*               LISTEN
tcp        0      0 10.192.25.199:8093      0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:8670            0.0.0.0:*               LISTEN

Por ejemplo, quiero obtener el puerto de escucha. Así que necesito usar el delimitador predeterminado awk agregado con ':'

# cat a.txt  | awk -F '[ ]+|:' '{print $5}'
65002
26895
111
18422
22
8888
50010
50075
8093
8670

Si solo desea probar el delimitador predeterminado, puede ejecutar

# cat a.txt  | awk -F '[ ]+' '{print $4}'
10.192.25.199:65002
127.0.0.1:26895
0.0.0.0:111
0.0.0.0:18422
0.0.0.0:22
10.192.25.199:8888
0.0.0.0:50010
0.0.0.0:50075
10.192.25.199:8093
0.0.0.0:8670

El resultado es el esperado.


La pregunta the default delimiter is only space for awk? es ambiguo, pero intentaré responder a las dos preguntas que podrías estar haciendo.

El valor predeterminado de FS variable (que contiene el separador de campo que le dice a awk cómo separar los registros en campos a medida que los lee) es un carácter de espacio único.

Lo que usa awk para separar registros en campos es un "separador de campo", que es una expresión regular con alguna funcionalidad adicional que solo se aplica cuando el separador de campo es un solo carácter en blanco. Esa funcionalidad adicional es que:

  1. Los espacios en blanco iniciales y finales se ignoran durante la división de campos.
  2. Los campos están separados en cadenas de caracteres de espacio contiguos que incluyen espacios en blanco, tabulaciones y saltos de línea.
  3. Si desea utilizar un carácter en blanco literal como separador de campo, debe especificarlo como [ ] en lugar de solo un carácter en blanco literal independiente como lo haría en una expresión regular.

Además de los separadores de campo que se usan para dividir registros en campos a medida que se lee la entrada, se usan en otros contextos, p. el tercer argumento para split() , por lo que es importante que sepa qué contextos requieren una cadena, una expresión regular o un campo, y la página del manual especifica claramente cada uno.

Entre otras cosas, lo anterior explica esto:

$ echo ' a b c ' | awk '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F' ' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F'[ ]' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'                              
5: <> <a> <b>

así que si no entiende por qué los 2 primeros producen el mismo resultado pero el último es diferente, pregunte.


Linux
  1. 9 potentes funciones incorporadas de Awk para numérico

  2. comprobando bibliotecas compartidas para cargadores no predeterminados

  3. comando cut o awk para imprimir el primer campo de la primera fila

  4. grep para el término y excluir otro término

  5. ¿Qué constituye un 'campo' para el comando de corte?

Los 5 mejores lanzadores de aplicaciones para Ubuntu

¿Cambiar Shell predeterminado para Terminator?

Tutorial de expresiones regulares para ejemplos de Linux (Sed y AWK)

¿La mejor utilidad de explorador de espacio de disco gráfico para Ubuntu?

¿Cuál es el archivo predeterminado para `hostname`?

¿Cómo cambiar el campo De:para correos electrónicos de Cron?