Me gustaría imprimir el número de caracteres en cada línea de un archivo de texto usando un comando de Unix. Sé que es simple con powershell
gc abc.txt | % {$_.length}
pero necesito el comando Unix.
Respuestas:
Utilice Awk.
awk '{ print length }' abc.txt
while IFS= read -r line; do echo ${#line}; done < abc.txt
Es POSIX, por lo que debería funcionar en todas partes.
Editar: Se agregó -r como lo sugirió William.
Editar: tenga cuidado con el manejo de Unicode. Bash y zsh, con la configuración regional correctamente establecida, mostrarán el número de puntos de código, pero el guión mostrará bytes, por lo que debe verificar lo que hace su shell. Y luego hay muchas otras posibles definiciones de longitud en Unicode de todos modos, por lo que depende de lo que realmente desee.
Editar: prefijo con IFS=
para evitar perder espacios iniciales y finales.
IFS=
el read
comando cuando desee leer datos arbitrarios. Entonces IFS= read -r
. read
usa el IFS
para dividir palabras, y aunque todas las palabras divididas se vuelven a pegar en la única variable disponible ( line
), no hay garantía de que se vuelvan a pegar con todos los caracteres separadores originales que tenían o solo uno potencialmente diferente unos. Por ejemplo, con el IFS predeterminado, la línea foo bar
podría volverse foo bar
, perdiendo 7 espacios. (Como cómo Stack Overflow perdió los espacios adyacentes en esa cadena de ejemplo en este comentario).
IFS
debería establecerse, pero el problema cuando no lo es es más sutil.
Probé las otras respuestas enumeradas anteriormente, pero están muy lejos de ser soluciones decentes cuando se trata de archivos grandes, especialmente una vez que el tamaño de una sola línea ocupa más de ~ 1/4 de la RAM disponible.
Tanto bash como awk absorben toda la línea, aunque para este problema no es necesario. Bash generará un error una vez que una línea sea demasiado larga, incluso si tiene suficiente memoria.
Implementé una secuencia de comandos de Python extremadamente simple y bastante no optimizada que, cuando se probó con archivos grandes (~ 4 GB por línea), no absorbió y es, con mucho, una mejor solución que las que se ofrecen.
Si este es un código crítico en el tiempo para la producción, puede reescribir las ideas en C o realizar mejores optimizaciones en la llamada de lectura (en lugar de leer solo un byte a la vez), después de probar que se trata de un cuello de botella.
El código asume que la nueva línea es un carácter de salto de línea, lo cual es una buena suposición para Unix, pero YMMV en Mac OS / Windows. Asegúrese de que el archivo termine con un salto de línea para asegurarse de que no se pase por alto el recuento de caracteres de la última línea.
from sys import stdin, exit
counter = 0
while True:
byte = stdin.buffer.read(1)
counter += 1
if not byte:
exit()
if byte == b'\x0a':
print(counter-1)
counter = 0
Aquí hay un ejemplo usando xargs
:
$ xargs -d '\n' -I% sh -c 'echo % | wc -c' < file
Prueba esto:
while read line
do
echo -e |wc -m
done <abc.txt
echo -e | wc -m
, no? Es un uso inútil de comandos; shell puede contar caracteres en una variable. Plus echo -e
es totalmente incompatible y funciona en la mitad de los proyectiles, mientras que comenzar con alguna secuencia de escape funciona en otro y nada en el resto.