Припустимо, у вас є цей файл:
$ 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