web-dev-qa-db-fra.com

Comment lire la Nième ligne d'un fichier et l'imprimer dans un nouveau fichier?

J'ai un dossier appelé foo. Foo a quelques autres dossiers qui peuvent avoir des sous-dossiers et des fichiers texte. Je veux trouver chaque fichier qui commence par le nom année et lire sa Nième ligne et l’imprimer dans un nouveau fichier. Par exemple, foo a un fichier appelé year1 et les sous-dossiers ont des fichiers appelés year2, year3, etc. Le programme imprimera la 1ère ligne de l'année1 dans un fichier appelé écriture, puis il imprimera la 2e ligne de l'année2 vers l'écriture de fichier, etc.

De plus, je ne comprenais pas vraiment comment faire une boucle for pour un fichier.

Jusqu'à présent j'ai:

#!/bin/bash

for year* in ~/foo
do
  Here I tried writing some code using the sed command but I can't think of something       else.
done

Je reçois également un message dans le terminal indiquant «année *», un identificateur non valide . Des idées?

13
captain

Sed peut vous aider.

Rappelez-vous que sed traitera normalement toutes les lignes d'un fichier ET imprimera chaque ligne du fichier.

Vous pouvez désactiver cette fonctionnalité et ne faire imprimer que les lignes qui vous intéressent en faisant correspondre un motif ou un numéro de ligne.

Donc, pour imprimer la 2e ligne du fichier 2, vous pouvez dire

sed -n '2p' file2 > newFile2

Pour imprimer la deuxième ligne puis arrêter le traitement, ajoutez la commande q (pour quitter) (vous devez également avoir des accolades pour regrouper les 2 commandes), c.-à-d. 

sed -n '2{p;q;}' file2 > newFile2

(Si vous traitez des fichiers volumineux, cela peut vous faire gagner beaucoup de temps).

Pour rendre cela plus général, vous pouvez changer le nombre en une variable qui contiendra un nombre, c.-à-d.

  lineNo=3
  sed -n "${lineNo}{p;q;}" file3 > newFile3

Si vous souhaitez que toutes vos lignes tranchées soient placées dans un fichier, utilisez la redirection 'add-shells' du shell, c'est-à-dire.

 for lineNo in 1 2 3 4 5 ; do
     sed -n  "${lineNo}{p;q;}" file${lineNo} >> aggregateFile
 done

Les autres publications, qui utilisent les résultats de find ... pour gérer votre liste de fichiers, constituent une excellente approche.

J'espère que ça aide.

32
shellter

Voici une façon de le faire:

awk "NR==$YEAR" $file
6
Karoly Horvath

Utilisez find pour localiser les fichiers souhaités, puis sed pour extraire ce que vous voulez:

find foo -type f -name year* |
while read file; do
    line=$(echo $file | sed 's/.*year\([0-9]*\)$/\1/')
    sed -n -e "$line {p; q}" $file
done

Cette approche:

  • Utilisez find pour générer une liste de fichiers dont le nom commence par la chaîne "année".
  • Pipe la liste de fichiers dans une boucle while pour éviter les longues lignes de commande
  • Utilise sed pour extraire le numéro de ligne souhaité du nom du fichier
  • Utilise sed pour n’imprimer que la ligne souhaitée, puis se fermer immédiatement. (Vous pouvez omettre la q et simplement écrire ${line}p, ce qui fonctionnerait mais serait potentiellement moins efficace. $file est trop gros. En outre, q peut ne pas être entièrement pris en charge sur toutes les versions de sed.)

Cela ne fonctionnera pas correctement pour les fichiers avec des espaces dans leurs noms.

3
Emil Sit

La meilleure façon qui fonctionne toujours, à condition de fournir 2 arguments:

$ touch myfile
$ touch mycommand
$ chmod +x mycommand
$ touch yearfiles
$ find / -type f -name year* >> yearfiles
$ nano mycommand
$ touch foo

Tapez ceci:

#/bin/bash
head -n $1 $2 >> myfile
less -n 1 myfile >> foo

Utilisez ^X, y et entrez pour enregistrer. Puis lancez ma commande:

$ ./mycommand 2 yearfiles
$ cat foo
year2

En supposant que vos fichiers year sont:

year1, year2, year3

De plus, maintenant que vous avez configuré, il vous suffit désormais d'utiliser $ ./mycommand LINENUMBER FILENAME.

1
Okx

Voici

sed ${index}'q;d' ${input_file} > ${output_file}
0
Karol Król

Votre tâche comporte deux sous-tâches: recherchez le nom de tous les fichiers de l'année, puis extrayez la Nième ligne. Considérez le script suivant:

for file in `find foo -name 'year*'`; do
     YEAR=`echo $file | sed -e 's/.*year\([0-9]*\)$/\1/'`
     head -n $YEAR $file | tail -n 1
done

L'appel de recherche trouve les fichiers correspondants pour vous dans le répertoire foo. La deuxième ligne extrait uniquement les chiffres à la fin du nom de fichier à partir du nom de fichier. La troisième ligne extrait ensuite les N premières lignes du fichier en ne conservant que la dernière des N premières lignes (en lecture: seule la Nième ligne). 

0
thiton
1.time head -5 emp.lst tail -1
It has taken time for execution is
real 0m0.004s
user 0m0.001s
sys 0m0.001s

or

2.awk 'NR==5' emp.lst
It has taken time for execution is
real 0m0.003s
user 0m0.000s
sys 0m0.002s

or 

3.sed -n '5p' emp.lst
It has taken time for execution is
real 0m0.001s
user 0m0.000s
sys 0m0.001s

or 

4.using some cute trick we can get this with cut command
cut -d “
“ -f 5 emp.lst
# after -d press enter ,it means delimiter is newline
It has taken time for execution is
real 0m0.001s
0
parmeet