Припустимо, у вас є цей файл:
$ 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
Є чотири елементи, які змінять значення вихідного файлу, прочитаного багатьма рішеннями Bash:
- Порожній рядок 4;
- Провідні або кінцеві пробіли на двох лініях;
- Підтримка значення окремих рядків (тобто кожен рядок є записом);
- Рядок 6 не закінчується CR.
Якщо ви хочете, щоб текст текстовий файл був рядок, включаючи порожні рядки та кінцеві рядки без CR, ви повинні використовувати цикл час, і ви повинні мати альтернативний тест для остаточного рядка.
Ось методи, які можуть змінити файл (порівняно з тим, що catповертається):
1) Втратити останній рядок та провідні та кінцеві пробіли:
$ 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'
(Якщо ви робите while IFS= read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txtзамість цього, ви зберігаєте провідні та кінцеві пробіли, але все одно втрачаєте останній рядок, якщо він не закінчується CR)
2) Використовуючи підстановку процесу на catзаповіт, читається весь файл одним глотком і втрачає значення окремих рядків:
$ 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'
(Якщо ви вилучите "з нього, $(cat /tmp/test.txt)ви прочитаєте файл слово за словом, а не одним глотком. Також, мабуть, не те, що призначено ...)
Найбільш надійний і найпростіший спосіб читати файл по черзі та зберігати всі інтервали:
$ 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'
Якщо ви хочете зняти провідні та торгові простори, видаліть IFS=деталь:
$ 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'
(Текстовий файл без закінчення \n, хоча досить поширений, вважається зламаним під POSIX. Якщо ви можете розраховувати на те, що \nвам не потрібно || [[ -n $line ]]в whileциклі, слід.)
Детальніше у FAQ FAQ