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?
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.
Voici une façon de le faire:
awk "NR==$YEAR" $file
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:
find
pour générer une liste de fichiers dont le nom commence par la chaîne "année".while
pour éviter les longues lignes de commandesed
pour extraire le numéro de ligne souhaité du nom du fichiersed
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.
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
.
Voici
sed ${index}'q;d' ${input_file} > ${output_file}
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).
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