Shell-Script
在 ‘while read -r’ 中將 ‘r’ 視為無
我有這行程式碼逐行讀取文本文件。
文本文件有時由 Windows 使用者生成,有時由 Unix 使用者生成。因此,有時我看到
\r\n
行尾,有時我只看到\n
.我希望我的腳本能夠處理這兩種情況並分別到達每一行,而不管換行符是
\r
, or\n
, or\r\n
, or\n\r
。while read -r textFileLines; do ... something ...; done < text_file.txt
此程式碼在
\n\r
每行末尾與(LF CR) 一起使用,但當我在行尾使用時不起作用!\r\n
測試
- 使用創建一個新的文本文件
Notepad++ v7.5.4
while read -r LINE; do echo "$LINE"; done < /cygdrive/d/test_text.txt
- 終端中的輸出:
first_line second_line third_string
為什麼沒有
fourth_output
顯示線?
如果您有一些文件是 DOS 文本文件,而一些文件是 Unix 文本文件,則您的腳本可以通過以下方式傳遞所有數據
dos2unix
:dos2unix <filename | while IFS= read stuff; do # do things with "$stuff" done
Unix 文本文件不會因此而被修改。
為了另外應對Mac換行符,我相信你應該能夠做到
dos2unix <filename | mac2unix | while IFS= read stuff; do # do things with "$stuff" done
最後一行沒有被
read
循環輸出,因為它沒有終止,因此根本不是一行。要檢測文件是否在最後一行沒有終止換行符,如果沒有,則添加一個,在
bash
:if [ "$( tail -c 1 filename )" != $'\n' ]; then printf '\n' >>filename fi
有關的:
為什麼沒有
fourth_output
顯示線?在您的圖像中,該文件在最後一行末尾缺少換行符。
read
僅當它讀取分隔符(換行符)時才返回 true,並且由於最後一行的末尾不存在該分隔符,因此read
返回 false,循環結束,並且不列印最後一個不完整的行。這與輸入無關,即使只有 NL,如果最後一行缺少 NL,行為也是一樣的。
在這裡,
file1
有兩行以 CRLF 行結尾:$ cat -A file1 foo^M$ bar^M$ $ while read x ; do echo "<$x>"; done < file1 >foo >bar
file2
缺少以第二行結尾的行:$ cat -A file2 ; echo foo^M$ bar $ while read x ; do echo "<$x>"; done < file2 >foo
如果你想讓循環也處理最後一行片段,你必須檢查
read
變數read
本身返回失敗時是否包含任何數據:$ while read -r x || [ "$x" ] ; do echo "<$x>"; done < file2 >foo <bar>
如果您想擺脫 CR,您可以在循環中將其刪除,例如
x=${x%$'\r'};
(在 Bash/ksh/zsh 中),或使用 or 等預處理tr -d '\r'
文件dos2unix
。