[英]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.