Shell-Script

在 ‘while read -r’ 中將 ‘r’ 視為無

  • August 1, 2018

我有這行程式碼逐行讀取文本文件。

文本文件有時由 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

引用自:https://unix.stackexchange.com/questions/456766