簡體   English   中英

如何刪除單行txt文件的行尾符號(使用sed/awk)?

[英]How to delete end-of-line sign (using sed/awk) of a single-line txt file?

僅當“列表”是包含單行(URL)而沒有結束行尾符號(“ $”)。 我試過了

sed -e 's/\r$//g'

sed -e 's/^M//g'

但我只能在文本編輯器中手動刪除結尾的“$”,轉到文件的最后一行(即第二行)並按鍵盤上的退格鍵。

將包含數百個 URL 的主文件拆分為單行文件並一次調用 php 函數是沒有問題的,但是必須有另一種簡單的方法(sed,awk?)來刪除結尾的“$”文件中(僅)行的結尾。

您的文件中沒有$ $是一個用於在正則表達式中表示字符串結束的符號(就像^表示字符串開始)。 在一次操作一行的工具中,它正在處理的字符串的結尾也是行的結尾,因此使用面向行的工具的人經常將$誤認為是行尾,因為在上下文中工具是一樣的。 $也用於其他工具(例如cat -E )作為行尾指示符。

一些術語/定義:

  • \\r是腳本中用於生成或匹配CR (回車)字符^M (控制-M)、ASCII 13 的轉義序列
  • \\n是腳本中用於生成或匹配LF (換行符)字符^J (control-J)、ASCII 10 的轉義序列
  • $是腳本中用於指示end-of-string (通常也是行結束)的正則表達式元字符,也被工具用於在顯示文本時指示行end-of-line
  • \\n (即單獨的LF )在 UNIX 中被認為是換行符
  • \\r\\n (即CRLF )被認為是 DOS 中的換行符(請參閱為什么我的工具輸出會覆蓋自身以及如何修復它?

所以當你這樣做時:

$ printf 'foo\n' | cat -vE
foo$

這並不意味着在foo的末尾有一個$ ,它只是cat顯示一個$來告訴你行尾的位置。 當你這樣做時:

$ printf 'foo\r\n' | cat -vE
foo^M$

^M (control-M)明確地向您展示了由\\r生成的CR (回車)字符,但$沒有明確地向您展示LF (換行)生成的^J (control-J)字符由\\n代替,它專門顯示不同的字符$以顯示行尾。 如果它確實向您顯示^J s,那么所有內容都將連接在一行上,這將很難閱讀。 考慮一下閱讀這個的難易程度:

$ printf 'the\nquick\nbrown\nfox\n' | cat -vE
the$
quick$
brown$
fox$

與如果輸出是這樣的:

$ printf 'the\nquick\nbrown\nfox\n' | some_other_tool
the^Jquick^Jbrown^Jfox^J

您永遠無法執行以下任一操作:

$ printf 'foo\nbar\n' | sed 's/$//' | cat -vE
foo$
bar$

$ printf 'foo\nbar\n' | sed 's/\n//' | cat -vE
foo$
bar$

要刪除 LF,因為 sed 在讀取輸入時已經消耗了 LF 並且$本身不是換行符,它是一個元字符,可讓您在正則表達式中說“匹配行尾”(在這種情況下,因為結束默認情況下,輸入字符串的末尾是 sed 的行尾)。

您可能會問 - 如果 sed 在讀取輸入時消耗了 LF 那么為什么在每行輸出的末尾都有 LF? 答案是 sed 向每個輸出行添加一個 LF,因此它輸出的是一個有效的 POSIX 文本文件(如果不終止 LF,您就沒有 POSIX 文本文件,因此任何后續工具對它所做的都是未定義的行為)。

但是,如果您使用的工具一次不讀取一行,則可以刪除 LF。 GNU sed 有一個-z選項來讀取 NUL 分隔的文本而不是 LF 分隔的文本,在這種模式下你可以刪除LF字符:

$ printf 'foo\nbar\n' | sed -z 's/\n//' | cat -vE
foobar$

現在您可以看到$ (字符串結尾元字符)與\\n (匹配 LF 字符的轉義序列)有何不同:

$ printf 'foo\nbar\n' | sed -z 's/$//' | cat -vE
foo$
bar$

$ printf 'foo\nbar\n' | sed -z 's/\n/<LF>/' | cat -vE
foo<LF>bar$

$ printf 'foo\nbar\n' | sed -z 's/$/<EOS>/' | cat -vE
foo$
bar$
<EOS>$

所以“你如何用 sed 刪除 LF”的快速答案? 這是 GNU sed 嗎:

$ printf 'foo\nbar\n' | sed -z 's/\n//g'
foobar$

並且如果您沒有 GNU sed(或者實際上即使您這樣做,因為假設沒有 NUL 作為輸入的 POSIX 文本文件,上述內容會立即將整個輸入讀入內存),那么您應該只使用 awk:

$ printf 'foo\nbar\n' | awk -v ORS= '1'
foobar$

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM