web-dev-qa-db-fra.com

comment supprimer les deux premières colonnes d'un fichier à l'aide de Shell (awk, sed, peu importe)

J'ai un fichier avec plusieurs lignes Dans chaque ligne, il y a plusieurs colonnes (champs) séparées par des "" Les nombres de colonnes dans chaque ligne sont différents Je veux supprimer les deux premières colonnes comment?

64
wenzi

Vous pouvez le faire avec cut:

cut -d " " -f 3- input_filename > output_filename

Explication:

  • cut: invoquer la commande cut
  • -d " ": utilise un seul espace comme délimiteur (cut utilise TAB par défaut)
  • -f: spécifier les champs à conserver
  • 3-: tous les champs commençant par le champ 3
  • input_filename: utilise ce fichier comme entrée
  • > output_filename: écrivez le résultat dans ce fichier.

Sinon, vous pouvez le faire avec awk:

awk '{$1=""; $2=""; sub("  ", " "); print}' input_filename > output_filename

Explication:

  • awk: invoquer la commande awk
  • $1=""; $2="";: définit les champs 1 et 2 sur la chaîne vide
  • sub(...);: nettoie les champs de sortie car les champs 1 et 2 seront toujours délimités par ""
  • print: affiche la ligne modifiée
  • input_filename > output_filename: comme ci-dessus.
130
sampson-chen

Voici une façon de le faire avec Awk qui est relativement facile à comprendre:

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

Il s'agit d'une simple commande awk sans motif, de sorte que l'action à l'intérieur de {} est exécutée pour chaque ligne d'entrée. 

L'action consiste à simplement imprimer la sous-chaîne en commençant par la position du troisième champ.

  • $0: toute la ligne de saisie
  • $3: 3ème champ
  • index(in, find): renvoie la position de find dans la chaîne in
  • substr(string, start): retourne une sous-chaîne commençant à index start

Si vous souhaitez utiliser un autre délimiteur, tel que la virgule, vous pouvez le spécifier avec l'option -F:

awk -F"," '{print substr($0, index($0, $3))}'

Vous pouvez également utiliser cette option sur un sous-ensemble des lignes d'entrée en spécifiant un modèle avant l'action dans {}. Seules les lignes correspondant au motif font exécuter l'action.

awk 'pattern{print substr($0, index($0, $3))}'

Où motif peut être quelque chose comme:

  • /abcdef/: utilise une expression régulière, fonctionne sur $ 0 par défaut.
  • $1 ~ /abcdef/: opère sur un champ spécifique.
  • $1 == blabla: utiliser la comparaison de chaînes
  • NR > 1: utilise le numéro d'enregistrement/ligne
  • NF > 0: utiliser le numéro de champ/colonne
21
raychi

Merci d'avoir posté la question. J'aimerais aussi ajouter le script qui m'a aidé.

awk '{ $1=""; print $0 }' file
12
Felipe Alvarez
awk '{$1=$2="";$0=$0;$1=$1}1'

Contribution

a b c d

Sortie

c d
8
Steven Penny

C'est assez simple de le faire avec seulement Shell

while read A B C; do
echo "$C"
done < oldfile >newfile
6
technosaurus

Vous pouvez utiliser sed:

sed 's/^[^ ][^ ]* [^ ][^ ]* //'

Ceci recherche les lignes commençant par un ou plusieurs non-blancs, un blanc, un autre ensemble de un ou plusieurs non-blancs et un autre blanc, et supprime le matériau correspondant, c'est-à-dire les deux premiers champs. Le [^ ][^ ]* est légèrement plus court que la notation [^ ]\{1,\} équivalente mais plus explicite, et le second risque de rencontrer des problèmes avec GNU sed (bien que si vous utilisez --posix en tant qu'option, même GNU sed ne peut pas le vider up). OTOH, si la classe de caractères à répéter était plus complexe, la notation numérotée gagne par souci de concision. Il est facile d’étendre cette option pour traiter "espace ou tabulation" comme séparateur, ou "plusieurs espaces" ou "plusieurs espaces ou onglets". Il peut également être modifié pour gérer des espaces (ou des onglets) facultatifs précédant le premier champ, etc.

Pour awk et cut, voir Sampson-Chen 's answer . Il existe d'autres moyens d'écrire le script awk, mais ils ne sont pas matériellement meilleurs que la réponse fournie. Notez que vous devrez peut-être définir le séparateur de champ explicitement (-F" ") dans awk si vous ne souhaitez pas que les onglets soient traités comme des séparateurs, ou vous pouvez avoir plusieurs espaces entre les champs. La norme POSIX cut ne prend pas en charge plusieurs séparateurs entre les champs; GNU cut a l'option -i utile mais non standard pour autoriser plusieurs séparateurs entre les champs.

Vous pouvez aussi le faire en pur Shell:

while read junk1 junk2 residue
do echo "$residue"
done < in-file > out-file
6
Jonathan Leffler

Perl:

Perl -lane 'print join(' ',@F[2..$#F])' File

awk:

awk '{$1=$2=""}1' File
4
Vijay

Cela pourrait fonctionner pour vous (GNU sed):

sed -r 's/^([^ ]+ ){2}//' file

ou pour les colonnes séparées par un ou plusieurs espaces blancs:

sed -r 's/^(\S+\s+){2}//' file
1
potong

Utilisez kscript

kscript 'lines.split().select(-1,-2).print()' file
0
Holger Brandl