Concha Z

Concha Z

Quero invocar um comando para cada linha da entrada padrão, como xargs, mas a linha deve ser passada como entrada padrão, não como um argumento de linha de comando:

cat some-file.txt | <magic> | wc -c
  • isso deve imprimir o número de caracteres em cada linha do arquivo.

Quais são minhas opções?

Responder1

Que tal um loop simples

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

Responder2

Um loop while-read é o mais claro. Se você quiser usar xargs para fazer algo para cada linha, você pode acabar com uma monstruosidade 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

Muito caro, pois você precisa gerar um processo bash para cada linha.

Responder3

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

No entanto, isso iráapenasimprima o número de caracteres em uma linha, uma linha por vez. Se você quiser algo mais legível, você pode querer um dos seguintes:

##  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 maior portabilidade você poderia usar printf '%s' "$i"em vez de todos os echo -ns

Responder4

Concha Z

Armazenar linhas em uma variável pode ser evitado usando a opção-e

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

-r\s como eles são

-eecoa a entrada em vez de atribuí-la a qualquer variável

pipefailfaz read -re | wc -ca saída com código de status diferente de zero assim que o faz read -re, o que acontecerá no final do arquivo

Infelizmente, esta opção não está disponível no Bash

informação relacionada