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 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
Cela fonctionne, mais c'est très compliqué et prend beaucoup de temps pour traiter de longs fichiers texte.
Existe-t-il un moyen plus simple de procéder?
Réponses:
iirc:
cat filename.txt | awk '{ print $2 $4 }'
ou, comme mentionné dans les commentaires:
awk '{ print $2 $4 }' filename.txt
la source
awk '{print $2,$4}' filename.txt
c'est mieux (pas de pipe, juste un programme appelé)cat
dans mes scripts bash au lieu de spécifier un nom de fichier, car la surcharge est minime et parce que la syntaxecat ... | ... > ...
montre très bien ce qu'est l'entrée et où va la sortie. Vous avez raison cependant, ce n'est pas vraiment nécessaire ici.< input awk '{ print $2 $4 }' > output
dans ce but.Vous pouvez utiliser la
cut
commande:cut -d' ' -f3,5 < datafile.txt
impressions
la
-d' '
- signifie, utiliserspace
comme délimiteur-f3,5
- prendre et imprimer la 3e et la 5e colonnele
cut
est beaucoup plus rapide pour les gros fichiers en tant que solution shell pure. Si votre fichier est délimité par plusieurs espaces, vous pouvez d'abord les supprimer, comme:sed 's/[\t ][\t ]*/ /g' < datafile.txt | cut -d' ' -f3,5
où le (gnu) sed remplacera tout
tab
space
caractères ou par un seulspace
.Pour une variante - voici aussi une solution perl:
perl -lanE 'say "$F[2] $F[4]"' < datafile.txt
la source
Par souci d'exhaustivité:
while read _ _ one _ two _; do echo "$one $two" done < file.txt
Au lieu de
_
une variable arbitraire (telle quejunk
), vous pouvez également utiliser. Le but est juste d'extraire les colonnes.Démo:
$ while read _ _ 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
la source
Une variante plus simple -
$ while read line do set $line # assigns words in line to positional parameters echo "$3 $5" done < file
la source
Si votre fichier contient n lignes, 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é, car tout ce que vous voulez faire est de boucler 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
while
boucle, la commande condition étant la commanderead
interne: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 le
read
builtin a en fait un support spécial pour remplir une variable de tableau, 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 l'
cut
utilitaire:cut -d' ' -f2,4 < /path/of/my/text > out.txt
(ou
awk
, comme le suggère Tom van der Woerdt, ouperl
, ou mêmesed
).la source
read
plutôtcut
parce qu'il est robuste contre plusieurs espaces entre les champs et que vous n'avez pas besoin de magie de tableau:while read word1 word2 word3 word4 rest; do doSomethingWith $word2 $word4; done
Si vous utilisez des données structurées, cela présente l'avantage supplémentaire de ne pas appeler un processus shell supplémentaire à exécuter
tr
et / oucut
ou quelque chose. ...(Bien sûr, vous voudrez vous protéger contre les mauvaises entrées avec des conditions et des alternatives saines.)
... while read line ; do lineCols=( $line ) ; echo "${lineCols[0]}" echo "${lineCols[1]}" done < $myFQFileToRead ; ...
la source