J'ai un fichier qui ressemble à ceci:
AE United Arab Emirates
AG Antigua & Barbuda
AN Netherlands Antilles
AS American Samoa
BA Bosnia and Herzegovina
BF Burkina Faso
BN Brunei Darussalam
Et j'aimerais inverser la commande, en imprimant d'abord tout sauf 1 $ puis 1 $:
United Arab Emirates AE
Comment puis-je faire le truc "tout sauf le champ 1"?
Réponses:
L'attribution
$1
fonctionne mais cela laissera un espace de premier plan:awk '{first = $1; $1 = ""; print $0, first; }'
Vous pouvez également trouver le nombre de colonnes
NF
et l'utiliser dans une boucle.la source
awk {'first = $1; $1=""; print $0'}|sed 's/^ //g'
$1=""
laisse un espace comme Ben Jackson l'a mentionné, alors utilisez unefor
boucle:Donc, si votre chaîne était "un deux trois", la sortie sera:
deux
trois
Si vous voulez le résultat sur une ligne, vous pouvez procéder comme suit:
Cela vous donnera: "deux trois"
la source
awk '{for(i=2;i<=NF;i++){ printf("%s",( (i>2) ? OFS : "" ) $i) } ; print ;}'
qui: imprime les champs 2 à NF, ajoute le séparateur de champ de sortie si nécessaire (c'est-à-dire, sauf avant $ 2). La dernière impression ajoute une dernière nouvelle ligne pour mettre fin à l'impression de la ligne en cours. Celui-ci fonctionnera si vous changez FS / OFS (c'est-à-dire que ce ne sera pas toujours "espace")Utilisez la
cut
commande avec l'--complement
option:la source
echo a b c | cut -d' ' -f 2-
est une alternativePeut-être la manière la plus concise:
Explication:
$(NF+1)=$1
: Générateur d'un "nouveau" dernier champ.$1=""
: Définissez le premier champ d'origine sur nullsub(FS,"")
: Après les deux premières actions,{$(NF+1)=$1;$1=""}
supprimez le premier séparateur de champ en utilisant sub. L'impression finale est implicite.la source
Supprimez le premier champ et le premier séparateur, et imprimez le résultat (
7
est une valeur non nulle donc imprimant $ 0).la source
1
? Je me demande l'utilisation de ce modèle et je voulais comprendre cela. Merci!Définir le premier champ sur
""
laisse une seule copie deOFS
au début de$0
. En supposant qu'ilOFS
ne s'agit que d'un seul caractère (par défaut, c'est un seul espace), nous pouvons le supprimer avecsubstr($0, 2)
. Ensuite, nous ajoutons la copie enregistrée de$1
.la source
Si vous êtes ouvert à une solution Perl ...
est une solution simple avec un séparateur entrée / sortie d'un espace, qui produit:
Ce prochain est un peu plus complexe
et suppose que le séparateur d'entrée / sortie est composé de deux espaces:
Ces options de ligne de commande sont utilisées:
-n
boucle autour de chaque ligne du fichier d'entrée, n'imprime pas automatiquement chaque ligne-l
supprime les nouvelles lignes avant le traitement et les rajoute par la suite-a
mode autosplit - divise les lignes d'entrée dans le tableau @F. Par défaut, diviser sur les espaces-F
modificateur autosplit, dans cet exemple se divise sur «» (deux espaces)-e
exécuter le code Perl suivant@F
est le tableau de mots dans chaque ligne, indexé commençant par 0$#F
est le nombre de mots dans@F
@F[1..$#F]
est une tranche de tableau de l'élément 1 au dernier élément@F[1..$#F,0]
est une tranche de tableau de l'élément 1 au dernier élément plus l'élément 0la source
Le séparateur de champ dans gawk (au moins) peut être une chaîne ainsi qu'un caractère (il peut aussi s'agir d'une expression régulière). Si vos données sont cohérentes, cela fonctionnera:
Cela fait deux espaces entre les guillemets.
la source
awk '{ tmp = $1; sub(/^[^ ]+ +/, ""); print $0, tmp }'
la source
Déplaçons tous les enregistrements vers le suivant et définissons le dernier comme premier:
Explication
a=$1
enregistrez la première valeur dans une variable temporaire.for (i=2; i<=NF; i++) $(i-1)=$i
enregistrer la Nième valeur de champ dans le (N-1) ième champ.$NF=a
enregistrez la première valeur ($1
) dans le dernier champ.{}1
véritable condition de faireawk
exécuter l'action par défaut:{print $0}
.De cette façon, si vous avez un autre séparateur de champ, le résultat est également bon:
la source
Une première tentative semble fonctionner pour votre cas particulier.
la source
Option 1
Il existe une solution qui fonctionne avec certaines versions de awk:
Explication:
Résultat:
Cependant, cela peut échouer avec les anciennes versions de awk.
Option 2
C'est:
Notez que ce qui doit être effacé, c'est l'OFS, pas le FS. La ligne est recalculée lorsque le champ $ 1 est attribué. Cela change toutes les exécutions de FS en un seul OFS.
Mais même cette option échoue toujours avec plusieurs délimiteurs, comme le montre clairement la modification de l'OFS:
Cette ligne affichera:
Cela révèle que les séries de FS sont changées en un seul OFS.
Le seul moyen d'éviter cela est d'éviter le recalcul du champ.
Une fonction qui peut éviter le recalcul est sub.
Le premier champ pourrait être capturé, puis supprimé de 0 $ avec sous, puis les deux réimprimés.
Option 3
Même si nous modifions le FS, l'OFS et / ou ajoutons plus de délimiteurs, cela fonctionne.
Si le fichier d'entrée est changé en:
Et la commande se transforme en:
La sortie sera (toujours en préservant les délimiteurs):
La commande peut être étendue à plusieurs champs, mais uniquement avec les awks modernes et avec l'option --re-intervalle active. Cette commande sur le fichier d'origine:
Sortira ceci:
la source
Si vous êtes ouvert à une autre solution Perl:
la source
Il y a aussi une option sed ...
Expliqué ...
Plus en détail expliqué ...
la source
Encore une autre façon ...
... cela rejoint les champs 2 à NF avec le FS et génère une ligne par ligne d'entrée
J'utilise ceci avec git pour voir quels fichiers ont été modifiés dans mon répertoire de travail:
la source
Un autre moyen simple d'utiliser la commande cat
la source