Valores separados por tabulaciones en awk

90

¿Cómo selecciono la primera columna de la cadena separada por TAB?

# echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F'\t' '{print $1}'

Lo anterior devolverá la línea completa y no solo "LOAD_SETTLED" como se esperaba.

Actualizar:

Necesito cambiar la tercera columna en los valores separados por tabulaciones. Lo siguiente no funciona.

echo $line | awk 'BEGIN { -v var="$mycol_new" FS = "[ \t]+" } ; { print $1 $2 var $4 $5 $6 $7 $8 $9 }' >> /pdump/temp.txt

Sin embargo, esto funciona como se esperaba si el separador es una coma en lugar de un tabulador.

echo $line | awk -v var="$mycol_new" -F'\t' '{print $1 "," $2 "," var "," $4 "," $5 "," $6 "," $7 "," $8 "," $9 "}' >> /pdump/temp.txt
shantanuo
fuente
4
awk 'COMIENZO {FS = "[\ t] +"}; {print $ 1} '# esto es lo que estaba buscando. ¿Es correcta mi búsqueda de Google? :)
shantanuo
3
Gracias a este comentario, he descubierto: awk 'BEGIN {FS="\t"}; {print $1,FS,$2,FS,$3}' myFile.txtimprimir valores delimitados por tabulaciones de las tres primeras columnas.
Wok
6
O quizás simplementeawk 'BEGIN {OFS="\t"}; {print $1,$2,$3}'
Josiah Yoder
3
Tanto GNU como BSD awk admiten la -vconfiguración de variables. Es feo usarlo BEGIN {FS="\t"}dentro de un programa en línea , y es probable que se objete cualquier contribución de código abierto que intente hacer de esa manera. Solo haga eso si está escribiendo un archivo de programa . Además, se desaconseja usar en -Flugar de -v FS=porque este último deja claro que solo FSse está configurando y no OFS. La confusión sobre ese último punto es lo que causó esta publicación en primer lugar. Por eso es importante el "buen estilo".
Bruno Bronosky
1
Por favor, nadie, nunca, debería hacer lo que demostró @Wok. No enumera los separadores de campo de [entrada] en su salida. Usted especifica un Separador de campo de salida a través de la OFSvariable.
Bruno Bronosky

Respuestas:

141

Debe configurar la OFSvariable (separador de campo de salida) para que sea una pestaña:

echo "$line" | 
awk -v var="$mycol_new" -F $'\t' 'BEGIN {OFS = FS} {$3 = var; print}'

(asegúrese de citar la $linevariable en la declaración de eco)

Glenn Jackman
fuente
6
¿Cuál es el propósito de $ en $ '\ t'?
Amr Mostafa
10
Respondiendo a mi propia pregunta de la Advanced Bash Scripting Guide : La construcción de expansión de cadenas entre comillas $ '...' es un mecanismo que usa valores octales o hexadecimales de escape ..., por ejemplo, quote = $ '\ 042'.
Amr Mostafa
5
@AmrMostafa, lástima que guía tiene una explicación engañosa que lleva a pensar que no lo hace la $de $'\t'que no se necesita. El wiki de Greg es mejor: "De estos, $'...'es el más común y actúa como comillas simples, excepto que las combinaciones con barra invertida se expanden según lo especificado por el estándar ANSI C".
Cristian Ciupitu
9
En retrospectiva, $'\t'no es necesario. awk entiende que la cadena "\t"es un carácter de tabulación
glenn jackman
5
Colaboradores de código abierto, les ruego que no envíen cosas como awk -F $'\t' 'BEGIN {OFS = FS} …'. Eso debería ser awk -v FS='\t' -v OFS='\t' '…'. Puede parecer pedante, pero ser inconsistente aumenta las posibilidades de que un colaborador posterior introduzca un error porque malinterpreta su código.
Bruno Bronosky
21

¡Asegúrate de que sean realmente pestañas! En bash, puede insertar una pestaña usandoC-v TAB

$ echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F$'\t' '{print $1}'
LOAD_SETTLED
Mahmoud Abdelkader
fuente
9

Utilizo las variables FSy OFSpara manipular archivos de zona BIND que están delimitados por tabulaciones. Aquí está uno de mis scripts https://gist.github.com/RichardBronosky/abe1652c2d5c78c35b92ad02bdf0d0af#file-dns_update-sh-L36-L39

La carne es:

awk -v FS='\t' -v OFS='\t' \
    -v record_type=$record_type \
    -v hostname=$hostname \
    -v ip_address=$ip_address '
$1==hostname && $3==record_type {$4=ip_address}
{print}
' $zone_file > $temp

Esta es una forma limpia y fácil de leer de hacer esto.

Bruno Bronosky
fuente
5
echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -v var="test" 'BEGIN { FS = "[ \t]+" } ; { print $1 "\t" var "\t" $3 }'
shantanuo
fuente
0

¿No debería funcionar esto?

echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk '{print $1}'
asadz
fuente