Dans AWK, est-il possible de spécifier des “fourchettes” de champs?
Dans AWK, est-il possible de spécifier des "fourchettes" de champs?
Exemple. Étant donné un onglet séparé fichier "toto" avec 100 champs par ligne, je veux imprimer seulement les champs de 32 à 57 pour chaque ligne, et enregistrer le résultat dans un fichier "de la barre". Ce que je fais maintenant:
awk 'BEGIN{OFS="\t"}{print $32, $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $50, $51, $52, $53, $54, $55, $56, $57}' foo > bar
Le problème, c'est qu'il est fastidieux de type et source d'erreurs.
Est-il une forme syntaxique qui me permet de dire la même chose en plus concis et moins enclins à faire des erreurs (comme "$32..$57") ?
- double possible de Imprimer Troisième Colonne à la Dernière Colonne
Vous devez vous connecter pour publier un commentaire.
Vous pouvez le faire en awk par l'utilisation de remise en intervalles. Par exemple, pour imprimer les champs 3-6 des enregistrements de ce fichier:
serait:
Je suis de la création d'un RE segment f pour représenter tous les domaines et en plus c'est de réussir séparateur de champ (pour des raisons de commodité), puis je suis sur que dans le gensub à supprimer 2 de ceux-là (je.e les 2 premiers champs), n'oubliez pas le prochain 4 pour référence ultérieure à l'aide de \3, puis supprimer ce qui vient après eux. Pour votre séparées par des tabulations fichier dans lequel vous souhaitez imprimer des champs 32-57 (c'est à dire le 26 champs après la première 31) vous pouvez utiliser:
Ci-dessus utilise GNU awk pour gensub() fonction. Avec d'autres awks vous souhaitez utiliser les sous() ou d'un match() et substr().
EDIT: Voici comment écrire une fonction pour faire le travail:
Juste set FS selon le cas. Notez qu'il sera besoin d'un réglage pour la valeur par défaut de FS si votre fichier d'entrée peut commencer par des espaces et/ou plusieurs espaces entre les champs et ne fonctionne que si votre FS est un caractère unique.
print gensub(,,s,,e,,)
au lieu de l'équivalent desplit(<input>,$0); for (i=s; i<=e; i++) printf "%s%s", $i, (i<e ? OFS : ORS)
En plus de la
awk
réponse par @Jerry, il y a d'autres alternatives:À l'aide de
cut
(en supposant l'onglet délimiteur par défaut):À l'aide de
perl
:Légèrement version révisée:
printf
en faisant unprintf "%s", $s
avant la boucle, à partir de votre boucle às+1
, utilisez toujours de l'OFS comme préfixe dans la boucle, et l'impression d'un\n
après la boucle.Je suis en retard mais c'est rapide à au point, donc je vais le laisser ici. Dans ce cas j'ai l'habitude de simplement supprimer les champs je n'ai pas besoin avec gsub et d'impression. Rapide et sale exemple, puisque vous savez que votre fichier délimité par des tabulations, vous pouvez supprimer les 31 premiers champs:
exemple de la suppression de 4 champs car paresseux:
De sortie:
C'est plus court à écrire, plus facile à mémoriser et utilise moins de CPU cycles, que d'horribles boucles.
Vous pouvez utiliser une combinaison de boucles et de
printf
pour que dans awk:Cela ressemble un peu hacky, cependant:
OFS
, etJe ne sais pas une manière de faire le champ de sélection de la plage en awk. Je sais comment faire pour déplacer les champs à la fin de l'entrée (voir ci-dessous), mais pas facile au début. Ci-dessous, la manière difficile à déplacer les champs au début.
Si vous connaissez un personnage
c
qui n'est pas inclus dans votre entrée, vous pouvez utiliser les éléments suivants script awk:MODIFIER:
Et j'ai juste pensé que vous pouvez toujours trouver un caractère qui n'est pas dans l'entrée: utilisation
\n
.sub("([^" FS "]*" FS "){" n "}","")
. Qui a l'avantage dans ce cas de ne pas le remplacement de tous les onglets dans l'entrée avec des espaces comme votre posté solution serait de faire, sauf si vous définissezOFS="\t"
. Vous aurez besoin de définir FS à \t trop bien sûr.sub
est la meilleure solution générale.- Je utiliser cette fonction simple, qui ne vérifie pas que le champ de gamme existe en la ligne.
(Je sais OP demandé "dans AWK" mais ... )
Bash expansion sur la ligne de commande pour générer les arguments de la liste;
explication ;
placés sur une seule ligne à l'aide de points-virgules, à l'intérieur de
$()
d'évaluer et d'élargir en place.Unofrtunately ne semblent pas avoir accès à mon compte plus, mais aussi de ne pas avoir 50 rep pour ajouter un commentaire, de toute façon.
De Bob réponse peut être simplifié beaucoup de l'utilisation de 'seq':
Le mineur inconvénient est que vous devez spécifier votre premier numéro de champ comme un inférieur.
Donc, pour obtenir les champs 3 à 7, je précise 2 comme premier argument.
seq-s ,\$ 2 7 définit le champ séparateur pour seq à ',$' et les rendements 2,$3,$4,$5,$6,$7
cut-d, -f2- jeux de délimiteur de champ à", " et réduit essentiellement de tout ce qui est avant la première virgule, en montrant tout à partir de la deuxième champ. Ainsi le $3,$4,$5,$6,$7
Lorsqu'il est combiné avec Bob réponse, nous obtenons: