Lignes de numérotation des scripts shell dans un fichier
Question
Je dois trouver un moyen plus rapide de numéroter les lignes d'un fichier de manière spécifique en utilisant des outils tels que awk et sed. J'ai besoin que le premier caractère de chaque ligne soit numéroté de cette façon: 1,2,3,1,2,3,1,2,3, etc.
Par exemple, si l'entrée était ceci:
line 1
line 2
line 3
line 4
line 5
line 6
line 7
La sortie doit ressembler à ceci:
1line 1
2line 2
3line 3
1line 4
2line 5
3line 6
1line 7
Voici un morceau de ce que j'ai. $ lignes est le nombre de lignes dans le fichier de données divisé par 3. Donc, pour un fichier de 21 000 lignes, je traite cette boucle 7 000 fois.
export i=0
while [ $i -le $lines ]
do
export start=`expr $i \* 3 + 1`
export end=`expr $start + 2`
awk NR==$start,NR==$end $1 | awk '{printf("%d%s\n", NR,$0)}' >> data.out
export i=`expr $i + 1`
done
En gros, cela prend 3 lignes à la fois, les numérote et s’ajoute à un fichier de sortie. C'est lent ... et puis certains! Je ne connais pas d'autre moyen plus rapide de le faire ... des idées?
La solution
C’est lent parce que vous lisez les mêmes lignes encore et encore. De plus, vous démarrez un processus awk
uniquement pour le fermer et en démarrer un autre. Mieux vaut tout faire en un coup:
awk '{print ((NR-1)%3)+1 $0}' $1 > data.out
Si vous préférez avoir un espace après le nombre:
awk '{print ((NR-1)%3)+1, $0}' $1 > data.out
Autres conseils
Essayez la nl
commande.
Voir https://linux.die.net/man/1/nl . (ou un autre lien vers la documentation qui apparaît lorsque vous utilisez Google pour & "man nl &"; ou la version du texte qui s'affiche lorsque vous exécutez man nl
à l'invite du shell).
L'utilitaire nl lit les lignes à partir du fichier nommé ou l'entrée standard si l'argument de fichier est omis, s'applique un filtre de numérotation de ligne configurable opération et écrit le résultat à la sortie standard.
modifier: Non, c'est faux, toutes mes excuses. La commande n
ne permet pas de redémarrer la numérotation toutes les <=> lignes, elle dispose uniquement d'une option pour redémarrer la numérotation après avoir trouvé un modèle. Je ferai de cette réponse une réponse du wiki de la communauté, car cela pourrait aider quelqu'un à connaître <=>.
Perl vient à l’esprit:
perl -pe '$_ = (($.-1)%3)+1 . $_'
devrait fonctionner. Il ne fait aucun doute qu’il existe un équivalent awk. Fondamentalement, ((line# - 1) MOD 3) + 1
.
Cela pourrait fonctionner pour vous:
sed 's/^/1/;n;s/^/2/;n;s/^/3/' input
awk '{printf "%d%s\n", ((NR-1) % 3) + 1, $0;}' "$@"
Python
import sys
for count, line in enumerate(sys.stdin):
stdout.write( "%d%s" % ( 1+(count % 3), line )
Vous n'avez pas besoin de quitter bash pour cela:
i=0; while read; do echo "$((i++ % 3 + 1)) $REPLY"; done < input
Cela devrait résoudre le problème. $ _ imprimera toute la ligne.
awk '{print ((NR-1)%3+1) $_}' < input
1line 1
2line 2
3line 3
1line 4
2line 5
3line 6
1line 7
# cat input
line 1
line 2
line 3
line 4
line 5
line 6
line 7