95 votes

Prendre la nième colonne dans un fichier texte

J'ai un fichier texte :

1 Q0 1657 1 19.6117 Exp
1 Q0 1410 2 18.8302 Exp
2 Q0 3078 1 18.6695 Exp
2 Q0 2434 2 14.0508 Exp
2 Q0 3129 3 13.5495 Exp

Je veux prendre le 2ème et le 4ème mot de chaque ligne comme ceci :

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

J'utilise ce code :

 nol=$(cat "/path/of/my/text" | wc -l)
 x=1
 while  [ $x -le "$nol" ]
 do
     line=($(sed -n "$x"p /path/of/my/text)
     echo ""${line[1]}" "${line[3]}""  >> out.txt
     x=$(( $x + 1 ))
 done

Il fonctionne, mais il est très compliqué et prend beaucoup de temps pour traiter les longs fichiers texte.

Existe-t-il un moyen plus simple de procéder ?

144voto

Tom van der Woerdt Points 18645

Iirc :

cat filename.txt | awk '{ print $2 $4 }'

ou, comme mentionné dans les commentaires :

awk '{ print $2 $4 }' filename.txt

72voto

jm666 Points 17312

Vous pouvez utiliser le cut commandement :

cut -d' ' -f3,5 < datafile.txt

imprime

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

le site

  • -d' ' - signifier, utiliser space comme délimiteur
  • -f3,5 - prendre et imprimer la 3ème et la 5ème colonne

En cut es beaucoup plus rapide pour les gros fichiers comme une solution purement shell. Si votre fichier est délimité par de multiples espaces, vous pouvez les supprimer en premier, comme :

sed 's/[\t ][\t ]*/ /g' < datafile.txt | cut -d' ' -f3,5

où le (gnu) sed remplacera tout tab o space avec un seul caractère space .

Pour une variante - voici aussi une solution en perl :

perl -lanE 'say "$F[2] $F[4]"' < datafile.txt

27voto

Johannes Weiß Points 19013

Dans un souci d'exhaustivité :

while read -r _ _ one _ two _; do
    echo "$one $two"
done < file.txt

Au lieu de _ une variable arbitraire (telle que junk ) peuvent également être utilisés. Le but est simplement d'extraire les colonnes.

Démonstration :

$ while read -r _ _ one _ two _; do echo "$one $two"; done < /tmp/file.txt
1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

9voto

AKA11 Points 101

Une autre variante simple -

$ while read line
  do
      set $line          # assigns words in line to positional parameters
      echo "$3 $5"
  done < file

4voto

ruakh Points 68789

Si votre fichier contient n lignes, alors votre script doit lire le fichier n fois ; donc si vous doublez la longueur du fichier, vous quadruplez la quantité de travail que votre script fait - et presque tout ce travail est simplement jeté, puisque tout ce que vous voulez faire est de boucler sur les lignes dans l'ordre.

Au lieu de cela, la meilleure façon de boucler sur les lignes d'un fichier est d'utiliser une fonction while boucle, avec la condition-commande étant la read builtin :

while IFS= read -r line ; do
    # $line is a single line of the file, as a single string
    : ... commands that use $line ...
done < input_file.txt

Dans votre cas, puisque vous voulez diviser la ligne en un tableau, et que la fonction read builtin a en fait un support spécial pour remplir une variable de type tableau, ce qui est ce que vous voulez, vous pouvez écrire :

while read -r -a line ; do
    echo ""${line[1]}" "${line[3]}"" >> out.txt
done < /path/of/my/text

ou mieux encore :

while read -r -a line ; do
    echo "${line[1]} ${line[3]}"
done < /path/of/my/text > out.txt

Cependant, pour ce que vous faites, vous pouvez simplement utiliser la fonction cut utilitaire :

cut -d' ' -f2,4 < /path/of/my/text > out.txt

(ou awk comme le suggère Tom van der Woerdt, ou bien perl ou encore sed ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X