Comment imprimer toutes les colonnes après un nombre particulier en utilisant awk?


Réponses:


82
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'

3
quelques légères améliorations:awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'
glenn jackman

Merci @glenn, c'est en effet un peu plus général. Quoi qu'il en soit - je conviendrai certainement qu'il serait préférable d'utiliser cutou perlpour cela. N'utilisez cela que si vous insistez vraiment pour l'avoir awk.
Amadan

1
@SiegeX: Il n'ajoute pas d'octets NUL, il laisse le FS en place entre chaque champ vide.
Suspendu jusqu'à nouvel ordre.

1
Veuillez consulter la réponse de @ Ascherer pour l'élégance.

3
@veryhungrymike: L'élégance, c'est bien, mais je préfère avoir raison. : p
Amadan

68

Lorsque vous voulez faire une gamme de champs, awkvous n'avez pas vraiment de moyen simple de le faire. Je recommanderais cutplutôt:

cut -d' ' -f 9- ./infile

Éditer

Ajout d'un délimiteur de champ d'espace car la valeur par défaut est un onglet. Merci à Glenn pour l'avoir signalé


15
Une chose à propos de cut est qu'il utilise un délimiteur spécifique (tabulation par défaut), où awk utilise des "espaces". Avec cut, 2 onglets consécutifs délimitent un champ vide.
glenn jackman

1
Comme @glennjackman l'a souligné, le délimiteur de awk est "espace blanc" (n'importe quel montant également). Ainsi, définir le délimiteur de coupe sur un seul espace ne correspondrait pas au comportement. malheureusement, la boucle est la meilleure que l'on puisse faire, alors ça a l'air.
poncha

Celui-ci ne fonctionne pas correctement. Essayez la commande find . | xargs ls -l | cut -d' ' -f 9-. Pour une raison quelconque, les espaces doubles sont également comptés. Exemple: lrwxrwxrwx 1 me me 21 Dec 12 00:00 ./file_a lrwxrwxrwx 1 me me 64 Dec 6 00:06 ./file_baboutira à./file_a 00:06 ./file_b
Marco Pashkov

@MarcoPashkov veuillez préciser que celui-ci ne fonctionne pas correctement , d'autant plus que vous utilisez exactement le même code dans votre pipeline. Au fait, vous ne
SiegeX

couper ne fait pas le travail ici. Par exemple, si votre entrée est "foo bar" (espace unique) pour une ligne, et "foo ___ bar" (c'est-à-dire plusieurs espaces, mais SO est trop intelligent pour l'afficher) pour une autre, cut les traitera différemment.
UKMonkey

54
awk '{print substr($0, index($0,$9))}'

Modifier : Notez que cela ne fonctionne pas si un champ avant le neuvième contient la même valeur que le neuvième.


3
celui-ci est génial!

10
@veryhungrymike: ... et ne fonctionne pas si un champ avant le neuvième contient la même valeur que le neuvième.
Amadan

6
Probablement à cause de la phrase classique "j'espère que votre fichier n'a pas ce problème". C'est un non-non total dans l'ingénierie s / w de déclarer: "nous n'allons pas perdre de temps à vérifier les erreurs pour l'entrée de valeurs négatives, par exemple, car 'nous espérons que l'utilisateur sera assez intelligent pour ne pas les essayer, écrasant notre outil '". HAHAHA! J'adore toujours entendre ça! (Je comme un bon sens de l' humour) Eh bien, comme les idiots font exist, il est du devoir du développeur de faire son truc idiot preuve ! Au lieu "d'espérer le bien de l'homme". C'est plutôt une attitude attendue des philosophes, pas des ingénieurs s / w ... LOL
syntaxerror

3
Je ne disais pas de ne pas vérifier les erreurs, mais si vous savez que vous n'allez pas rencontrer le problème, alors cette solution est bonne, comme je l'ai dit. Mais merci pour le vote défavorable inutile @syntaxerror. Cette solution fonctionnera pour certains, comme le montreront les 19 votes positifs (actuellement), mais si ce n'est pas le cas, ne l'utilisez pas pour votre solution. Il existe de nombreuses façons de résoudre le problème du PO.
Ascherer

1
Si vous utilisez awk sur la ligne de commande dans votre travail quotidien, c'est certainement la solution que vous recherchez. N'est-ce pas évident? La vérification des erreurs, etc., n'a pas vraiment d'importance dans ce cas puisque vous le saisissez et que vous pouvez attraper ce genre de choses avant d'appuyer sur Entrée (personnellement, je ne pense pas que awk devrait être utilisé pour autre chose de toute façon, c'est pourquoi nous 'ai perl, python, tcl et environ 100 autres langages de script, meilleurs, plus rapides et moins ennuyeux!)' Bien sûr, je donne peut-être trop de crédit à mes collègues développeurs de logiciels et ils ont vraiment besoin d'une vérification des erreurs même sur les éléments qu'ils tapent à la volée (??)
osirisgothra

11
sed -re 's,\s+, ,g' | cut -d ' ' -f 9-

Au lieu de traiter des espaces de largeur variable, remplacez tous les espaces par un seul espace. Ensuite, utilisez simple cutavec les champs d'intérêt.

Il n'utilise pas awk donc n'est pas pertinent mais semble approprié compte tenu des autres réponses / commentaires.


1
Veuillez donner une réponse plus approfondie, sinon postez-la en tant que commentaire à la question.
Alper Turan

Ceci est idéal pour une ps faux | utilisation. N'ayez jamais peur d'admettre que l'outil XYZ n'est pas le plus approprié.
kevinf

10

Généralement, perl remplace awk / sed / grep et. al., et est beaucoup plus portable (en plus d'être simplement un meilleur canif).

perl -lane 'print "@F[8..$#F]"'

Timtowtdi s'applique bien sûr.


Vous devez ajouter une option de ligne de commande -lou ajouter \nà l'instruction d'impression.
glenn jackman

@glenn jackman: Peut-être. Non obligatoire si elle fait partie d'un autre message, ou est assignée à une variable, etc. En ce qui concerne «mieux», perl semble certainement mieux dans le petit. Peut sembler très désordonné dans le grand, certes.
bobbogo

Ne vous méprenez pas, j'aime Perl. J'adore awk pour ce que c'est.
glenn jackman

Mon appareil intégré n'est pas livré avec Perl, mais il a awk.
Sepero

Downvoter parce que la question demandait comment faire cela dans awk, pas perl, ruby, java, python, bash.
Tom Harrison

3
awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

Cela coupe ce qui est avant le champ nr., N donné et imprime tout le reste de la ligne, y compris le champ nrN et en conservant l'espacement d'origine (il ne reformate pas). Cela n'a pas d'importance si la chaîne du champ apparaît également ailleurs dans la ligne, ce qui est le problème avec la réponse d'Ascherer.

Définissez une fonction:

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

Et utilisez-le comme ceci:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost   

La sortie conserve tout, y compris les espaces de fin Pour N = 0, elle renvoie la ligne entière, telle quelle, et pour n> NF la chaîne vide


C'est une bonne idée. Cela ne fonctionne pas tout à fait sur un Mac actuel utilisant gawk typique, car 0 $ s'effondre. Le correctif consiste à définir une variable sur $ 0 comme première étape, telle que: '{s = $ 0; ... imprimer substr (s, index (s, m) +1}
joelparkerhenderson

1

Voici un exemple de ls -lsortie:

-rwxr-----@ 1 ricky.john  1493847943   5610048 Apr 16 14:09 00-Welcome.mp4
-rwxr-----@ 1 ricky.john  1493847943  27862521 Apr 16 14:09 01-Hello World.mp4
-rwxr-----@ 1 ricky.john  1493847943  21262056 Apr 16 14:09 02-Typical Go Directory Structure.mp4
-rwxr-----@ 1 ricky.john  1493847943  10627144 Apr 16 14:09 03-Where to Get Help.mp4

Ma solution pour imprimer quoi que ce soit après $9estawk '{print substr($0, 61, 50)}'



0

Pour afficher les 3 premiers champs et imprimer les champs restants, vous pouvez utiliser:

awk '{s = ""; for (i=4; i<= NF; i++) s= s $i : "; print $1 $2 $3 s}' filename

où $ 1 $ 2 $ 3 sont les 3 premiers champs.


0
function print_fields(field_num1, field_num2){
    input_line = $0

    j = 1;
    for (i=field_num1; i <= field_num2; i++){
        $(j++) = $(i);

    }
    NF = field_num2 - field_num1 + 1;
    print $0

    $0 = input_line
}

0

Utiliser couper au lieu de awk et résoudre les problèmes de détermination de la colonne à partir de laquelle commencer en utilisant la commande -c character cut.

Ici, je dis, donnez-moi tous sauf les 49 premiers caractères de la sortie.

 ls -l /some/path/*/* | cut -c 50-

le /*/*/ à la fin de la commande ls indique: montrez-moi aussi ce qu'il y a dans les sous-répertoires.

Vous pouvez également extraire certaines plages de caractères ala (à partir de la page de manuel cut). Par exemple, affichez les noms et les heures de connexion des utilisateurs actuellement connectés:

       who | cut -c 1-16,26-38
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.