Suponha que você tenha este arquivo:
$ cat /tmp/test.txt
Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR
Existem quatro elementos que alterarão o significado da saída do arquivo lida por muitas soluções Bash:
- A linha em branco 4;
- Espaços iniciais ou finais em duas linhas;
- Manter o significado de linhas individuais (ou seja, cada linha é um registro);
- A linha 6 não terminou com um CR.
Se você deseja que o arquivo de texto linha por linha, incluindo linhas em branco e linhas de terminação sem CR, use um loop while e faça um teste alternativo para a linha final.
Aqui estão os métodos que podem alterar o arquivo (em comparação com o que cat
retorna):
1) Perca a última linha e os espaços à esquerda e à direita:
$ while read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
(Se while IFS= read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
preferir, você preserva os espaços à esquerda e à direita, mas ainda perde a última linha se não terminar com CR)
2) O uso da substituição de processo com o cat
will lê o arquivo inteiro de uma só vez e perde o significado de linhas individuais:
$ for p in "$(cat /tmp/test.txt)"; do printf "%s\n" "'$p'"; done
'Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR'
(Se você remover a "
partir de $(cat /tmp/test.txt)
você ler a palavra arquivo por palavra, em vez de um só gole. Além disso, provavelmente, não o que se pretende ...)
A maneira mais robusta e simples de ler um arquivo linha por linha e preservar todo o espaçamento é:
$ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
' Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space '
'Line 6 has no ending CR'
Se você deseja remover os espaços de liderança e negociação, remova a IFS=
peça:
$ while read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
'Line 6 has no ending CR'
(Um arquivo de texto sem terminação \n
, embora bastante comum, é considerado quebrado no POSIX. Se você puder contar com a trilha \n
que não precisa, || [[ -n $line ]]
nowhile
loop.)
Mais no FAQ do BASH