concha Z

concha Z

Quiero invocar un comando para cada línea de la entrada estándar, muy parecido a xargs, pero la línea debe pasarse como entrada estándar, no como un argumento de línea de comando:

cat some-file.txt | <magic> | wc -c
  • esto debería imprimir el número de caracteres en cada línea del archivo.

¿Cuáles son mis opciones?

Respuesta1

¿Qué tal un bucle simple?

while IFS= read -r line ;
do
   printf "%s" "$line" | wc -c
done < some-file.txt

Respuesta2

Un bucle while-read es el más claro. Si quieres usar xargs para hacer algo para cada línea, puedes terminar con una monstruosidad como esta:

printf "%s\n" "foo bar" one " 1 2 3" | 
xargs -d '\n' -n 1 -I LINE bash -c 'wc -c <<< "LINE"'
8
4
7

Bastante caro ya que tienes que generar un proceso bash para cada línea.

Respuesta3

cat file.txt | while IFS= read -r i; do echo -n "$i" | wc -c; done
##  or (better):
while IFS= read -r i; do echo -n "$i" | wc -c; done < file.txt

Sin embargo, esto serájustoimprime el número de caracteres en una línea, una línea a la vez. Si desea algo más legible, es posible que desee uno de los siguientes:

##  Prints the contents of each line underneath the character count:
while IFS= read -r i; do echo -n "$i" | wc -c; echo "$i"; done < file.txt
##  Prints the line number alongside the character count:
n=0; while IFS= read -r i; do n=$((n+1)); echo -n "line number $n : "; echo -n "$i" | wc -c; done < file.txt

Para una mayor portabilidad se puede utilizar printf '%s' "$i"en lugar de todos los echo -ns

Respuesta4

concha Z

Se puede evitar almacenar líneas en una variable usando la opción-e

setopt pipefail
cat some-file.txt |
  
  while read -re | wc -c
  do
  done

-rlee \s como son

-ehace eco de la entrada en lugar de asignarla a cualquier variable

pipefailsale read -re | wc -ccon un código de estado distinto de cero tan pronto como lo hace read -re, lo cual sucederá al final del archivo

Desafortunadamente, esta opción no está disponible en Bash.

información relacionada