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
) - elawk
predeterminado en algunos distribuciones de Linux - Mawk (
mawk
) - elawk
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).
- El valor predeterminado exigido por POSIX es una nueva línea , también conocido como
-
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.
- En
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 cuandoRS
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 elRS
predeterminado está en vigor, elsplit()
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.
- Aunque los registros de entrada no contendrá
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 deFS
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.
- Por ejemplo, configurar
- 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 .
- 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.
-
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 deFS
.
- Con
-P
en vigor yRS
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íoRS
,\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:
- Los espacios en blanco iniciales y finales se ignoran durante la división de campos.
- Los campos están separados en cadenas de caracteres de espacio contiguos que incluyen espacios en blanco, tabulaciones y saltos de línea.
- 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.