Je ne sais pas trop pourquoi cela a 87 votes positifs, il peut certainement être amélioré avec un exemple au moins.
Arj
Probablement parce que la question est extrêmement simple par nature et facile à comprendre sans exemple, ce qui est rare, mais dans ce cas, cela semble fonctionner. Le problème ici n'est pas le manque d'informations je pense, mais plutôt le fait que cela montre un manque de recherche indépendante.
DryLabRebel
Cette question est également un double de cette question.
Vous avez besoin d'une virgule - puisque nous sommes pointilleux aujourd'hui: l'espace concatène les champs, la virgule sépare les champs dans une instruction d'impression. Cela fusionnera les deux champs
Juste pour ajouter au commentaire précédent, le problème avec l'utilisation '{print $x,"\t",$y}'est que awk interprète chaque variable séparée par des virgules comme son propre champ, donc le résultat sera en fait field1<space><tab><space>field2, (car il utilisera un délimiteur d'espace blanc par défaut) par opposition à field1<tab>field2ce qui est probablement ce vous attendez. l'utilisation du séparateur de champ de sortie (OFS) est presque toujours ce que vous voulez.
DryLabRebel
13
awk '{print $NF-1, $NF}' inputfile
Remarque: cela ne fonctionne que s'il existe au moins deux colonnes. Sur les enregistrements avec une colonne, vous obtiendrez un faux"-1 column1"
Essayez et voyez. Cela fonctionne avec Solaris 9 awk & nawk. L'alternative est $ (NF-1)
jim mcnamara
1
@coaddict - Je suppose que vous n'avez pas travaillé avec différentes implémentations awk. De vieux comportements awks ont été (peut-être à tort) mis en avant. Je n'ai pas de gawk à tester - ce à quoi vous faites probablement référence. Je ne sais donc pas avec certitude pourquoi votre commentaire a été ignoré. Linux awk hors de la boîte est généralement gawk. Je vais tester et poster en retour. En attendant, essayez Soalris ou HPUX ou DGX ou autre pour voir ce que je veux dire par vieux awk.
jim mcnamara
6
Vous avez probablement été amené à penser que cela fonctionnait parce que vous avez essayé echo 1 2 3 | awk .... $NF-1est ($NF) - 1dans chaque awkmise en œuvre.
Stephane Chazelas
Le code source "One True Awk" a plus de 40 conflits dans la yaccgrammaire, ce qui est ironique étant donné ce que le A représente dans awk. Différentes versions de awk analysant les choses différemment? Grosse surprise!
Kaz
1
@THESorcerer, essayez avec echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- ou toute autre entrée où le 2ème dernier champ n'est pas un de moins que le dernier champ.
glenn jackman
6
@jim mcnamara: essayez d'utiliser des parenthèses pour autour NF, c'est-à $(NF-1)- dire et $(NF)au lieu de $NF-1et $NF(fonctionne sur Mac OS X 10.6.8 pour FreeBSD awket gawk).
echo '
1 2
2 3
one
one two three
'| gawk '{if (NF >= 2) print $(NF-1), $(NF);}'# output:# 1 2# 2 3# two three
Nous avions déjà envisagé () plus tôt. Je pensais que nous discutions de l'origine du comportement original de l'ancien awk.
jim mcnamara
+1 pour une réponse avec explicite $(NF-1)- qui au moins est plus portable que $NF-1; c'est nettement moins ambigu. $(NF)est exagéré, cependant - $NFfera juste . Se protéger contre les lignes de moins de 2 colonnes vaut également la peine, car avec des lignes à une colonne, vous obtiendrez la première valeur de la première colonne deux fois , et avec des lignes de colonne zéro - c'est-à-dire vides - la commande awk échouerait complètement en raison d'une tentative pour accéder à un champ d'index -1.
mklement0
1
l'utilisation de gawk présente le problème:
gawk '{ print $NF-1, $NF}' filename1223-1 one-1 three# cat filename1223
one
one two three
Je viens de mettre gawk sur Solaris 10 M4000: Donc, gawk est le cuplrit sur le problème $ NF-1 vs $ (NF-1). Question suivante que dit POSIX? par:
Il n'y a pas de direction dans un sens ou dans l'autre. Pas bon. gawk implique une soustraction, d'autres awks impliquent un numéro de champ ou une soustraction. hmm.
Les 2 premières lignes de votre exemple de fichier d'entrée ne sont pas utiles car elles produisent la même sortie avec l'un ou l' autre comportement. Pouvez-vous s'il vous plaît reconfirmer que Solaris awk ne se comporte en effet PAS comme gawk dans ce cas?
mklement0
Quant à votre lien vers la spécification awk: L'argument anecdotique pour l'utilisation $(NF-1)est que les deux exemples de calcul de l'index de champ dans la spécification utilisent tous deux cette forme: $(NF-1)et $(NF+2). Ensuite, il y a la section "Expressions dans awk", qui indique $exprcomme ayant une priorité [beaucoup] plus élevée que expr - expr. Puisque NFest une expression elle-même, $NF-1devrait s'évaluer ($NF)-1. Même SI, après tout, il existe en effet des implémentations awk qui évaluent $NF-1comme $(NF-1), la leçon apprise ici est que l'utilisation $(NF-1)est le choix sûr et portable.
Réponses:
Vous pouvez utiliser la variable
NF
qui correspond au nombre total de champs dans l'enregistrement d'entrée:cela suppose que vous ayez au moins 2 champs.
la source
awk '{print $(NF-1) "\t" $NF}' file
ouawk '{print $(NF-1), $NF}' file
ouawk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file
.'{print $x,"\t",$y}'
est que awk interprète chaque variable séparée par des virgules comme son propre champ, donc le résultat sera en faitfield1<space><tab><space>field2
, (car il utilisera un délimiteur d'espace blanc par défaut) par opposition àfield1<tab>field2
ce qui est probablement ce vous attendez. l'utilisation du séparateur de champ de sortie (OFS) est presque toujours ce que vous voulez.Remarque: cela ne fonctionne que s'il existe au moins deux colonnes. Sur les enregistrements avec une colonne, vous obtiendrez un faux
"-1 column1"
la source
echo 1 2 3 | awk ...
.$NF-1
est($NF) - 1
dans chaqueawk
mise en œuvre.yacc
grammaire, ce qui est ironique étant donné ce que le A représente dans awk. Différentes versions de awk analysant les choses différemment? Grosse surprise!echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'
- ou toute autre entrée où le 2ème dernier champ n'est pas un de moins que le dernier champ.@jim mcnamara: essayez d'utiliser des parenthèses pour autour
NF
, c'est-à$(NF-1)
- dire et$(NF)
au lieu de$NF-1
et$NF
(fonctionne sur Mac OS X 10.6.8 pour FreeBSDawk
etgawk
).la source
$(NF-1)
- qui au moins est plus portable que$NF-1
; c'est nettement moins ambigu.$(NF)
est exagéré, cependant -$NF
fera juste . Se protéger contre les lignes de moins de 2 colonnes vaut également la peine, car avec des lignes à une colonne, vous obtiendrez la première valeur de la première colonne deux fois , et avec des lignes de colonne zéro - c'est-à-dire vides - la commande awk échouerait complètement en raison d'une tentative pour accéder à un champ d'index -1.l'utilisation de gawk présente le problème:
Je viens de mettre gawk sur Solaris 10 M4000: Donc, gawk est le cuplrit sur le problème $ NF-1 vs $ (NF-1). Question suivante que dit POSIX? par:
Il n'y a pas de direction dans un sens ou dans l'autre. Pas bon. gawk implique une soustraction, d'autres awks impliquent un numéro de champ ou une soustraction. hmm.
la source
$(NF-1)
est que les deux exemples de calcul de l'index de champ dans la spécification utilisent tous deux cette forme:$(NF-1)
et$(NF+2)
. Ensuite, il y a la section "Expressions dans awk", qui indique$expr
comme ayant une priorité [beaucoup] plus élevée queexpr - expr
. PuisqueNF
est une expression elle-même,$NF-1
devrait s'évaluer($NF)-1
. Même SI, après tout, il existe en effet des implémentations awk qui évaluent$NF-1
comme$(NF-1)
, la leçon apprise ici est que l'utilisation$(NF-1)
est le choix sûr et portable.essayez avec ça
la source
Veuillez essayer ceci pour prendre en compte tous les scénarios possibles:
ou
ou
la source