Valeurs séparées par des tabulations dans awk

90

Comment sélectionner la première colonne de la chaîne séparée par TAB?

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

Ce qui précède renverra la ligne entière et pas seulement "LOAD_SETTLED" comme prévu.

Mise à jour:

J'ai besoin de changer la troisième colonne dans les valeurs séparées par tabulation. Ce qui suit ne fonctionne pas.

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

Cela fonctionne cependant comme prévu si le séparateur est une virgule au lieu d'une tabulation.

echo $line | awk -v var="$mycol_new" -F'\t' '{print $1 "," $2 "," var "," $4 "," $5 "," $6 "," $7 "," $8 "," $9 "}' >> /pdump/temp.txt
shantanuo
la source
4
awk 'BEGIN {FS = "[\ t] +"}; {print $ 1} '# c'est ce que je cherchais. Ma recherche Google est-elle correcte? :)
shantanuo
3
Grâce à ce commentaire, j'ai découvert: awk 'BEGIN {FS="\t"}; {print $1,FS,$2,FS,$3}' myFile.txtpour imprimer les valeurs délimitées par des tabulations des trois premières colonnes.
Wok
6
Ou peut-être simplementawk 'BEGIN {OFS="\t"}; {print $1,$2,$3}'
Josiah Yoder
3
Le support awk GNU et BSD -vpour la définition des variables. C'est moche à utiliser BEGIN {FS="\t"}dans un programme en ligne , et toute contribution open source que vous essayez de faire comme celle-ci est susceptible d'être contestée. Ne faites cela que si vous écrivez un fichier programme . En outre, il est déconseillé d'utiliser à la -Fplace de -v FS=car ce dernier indique clairement que seul FSest défini et non OFS. La confusion sur ce dernier point est ce qui a causé ce message en premier lieu. C'est pourquoi le «bon style» est important.
Bruno Bronosky
1
S'il vous plaît, personne, jamais, ne devrait faire ce que @Wok a démontré. Vous n'énumérez pas les séparateurs de champs [Entrée] dans votre sortie. Vous spécifiez un séparateur de champ de sortie via la OFSvariable.
Bruno Bronosky

Réponses:

141

Vous devez définir la OFSvariable (séparateur de champ de sortie) comme un onglet:

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

(assurez-vous de citer la $linevariable dans l'instruction echo)

Glenn Jackman
la source
6
Quel est le but du $ dans $ '\ t'?
Amr Mostafa
10
Répondre à ma propre question du Guide de script avancé Bash : La construction d'extension de chaîne entre guillemets $ '...' est un mécanisme qui utilise des valeurs octales ou hexadécimales échappées ..., par exemple, quote = $ '\ 042'.
Amr Mostafa
5
@AmrMostafa, trop mauvais ce guide a une explication trompeuse conduisant à penser que vous ne l' $en $'\t'est pas nécessaire. Le wiki de Greg est meilleur: "Parmi ceux-ci, $'...'est le plus courant, et agit comme des guillemets simples sauf que les combinaisons échappées par une barre oblique inverse sont développées comme spécifié par la norme ANSI C".
Cristian Ciupitu
9
Avec le recul, le $'\t'n'est pas nécessaire. awk comprend que la chaîne "\t"est un caractère de tabulation
glenn jackman
5
Contributeurs Open Source, je vous en prie, veuillez ne pas soumettre de choses comme awk -F $'\t' 'BEGIN {OFS = FS} …'. Cela devrait être awk -v FS='\t' -v OFS='\t' '…'. Cela peut sembler pédant, mais être incohérent augmente les chances qu'un contributeur ultérieur introduise un bogue parce qu'il comprend mal votre code.
Bruno Bronosky
21

Assurez-vous que ce sont vraiment des onglets! Dans bash, vous pouvez insérer un onglet en utilisantC-v TAB

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

J'utilise les variables FSet OFSpour manipuler les fichiers de zone BIND délimités par des tabulations. Voici l'un de mes scripts https://gist.github.com/RichardBronosky/abe1652c2d5c78c35b92ad02bdf0d0af#file-dns_update-sh-L36-L39

La viande de celui-ci est:

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

C'est une manière claire et facile à lire de faire cela.

Bruno Bronosky
la source
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
la source
0

Cela ne devrait-il pas fonctionner?

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