是的,我知道有許多問題(例如(0)或(1))似乎問的一樣,但 AFAICS 沒有一個真正回答我想要的。
我想要的是,用 string 替換任何出現的換行符(LF)\n,沒有隱式假定的換行符......并且這與POSIX 僅實用程式(并且沒有 GNU 擴展或 Bashisms)和輸入從 stdin 讀取沒有緩沖這是期望的。
例如:
printf 'foo' | magic應該給fooprintf 'foo\n' | magic應該給foo\nprintf 'foo\n\n' | magic應該給foo\n\n
通常給出的答案,不要這樣做,例如:
- awk
printf 'foo' | awk 1 ORS='\\n給出foo\n,而它應該給出,所以在沒有換行符時foo
添加一個。\n - sed
僅適用foo于所有其他情況,例如:
printf 'foo\n' | sed ':a;N;$!ba;s/\n/\\n/g'給foo,而它應該給foo\n
錯過最后一個換行符。
由于我不想要任何型別的緩沖,我不能只查看輸入是否以換行符結尾,然后手動添加缺少的。
無論如何……它會使用 GNU 擴展。
sed -z 's/\n/\\n/g'
確實有效(甚至正確地保留了 NUL),但同樣是 GNU 擴展。 - tr
只能替換為一個字符,而我需要兩個。
到目前為止,我唯一可行的解??決方案是 perl:
perl -p -e 's/\n/\\n/'
它在所有情況下都可以正常作業,但正如我所說,我想為只有基本 POSIX 實用程式的環境提供一個解決方案(所以沒有 Perl 或使用任何 GNU 擴展)。
提前致謝。
uj5u.com熱心網友回復:
以下將適用于正在使用的所有 POSIX 版本的工具以及任何 POSIX 文本允許的字符作為輸入,無論是否存在終止換行符:
$ magic() { { cat -u; printf '\n'; } | awk -v ORS= '{print sep $0; sep="\\n"}'; }
$ printf 'foo' | magic
foo$
$ printf 'foo\n' | magic
foo\n$
$ printf 'foo\n\n' | magic
foo\n\n$
該函式首先在傳入的管道資料中添加一個換行符,以確保 awk 正在讀取的是有效的 POSIX 文本檔案(必須以換行符結尾),因此它可以保證在所有 POSIX 兼容的 awk 中作業,然后 awk 命令丟棄該終止我們添加的換行符并根據需要替換所有其他行"\n"。
上面唯一一個必須在沒有終止換行符的情況下處理輸入的實用程式是cat,但是 POSIX 只討論作為輸入的“檔案” cat ,而不是awk和sed規范中的“文本檔案” ,因此每個符合 POSIX 的catcan處理沒有終止換行符的輸入。
uj5u.com熱心網友回復:
這是一個tr sed適用于任何 POSIX shell 的解決方案,因為它不呼叫任何 gnu 實用程式:
printf 'foo' | tr '\n' '\7' | sed 's/\x7/\\n/g'
foo
printf 'foo\n' | tr '\n' '\7' | sed 's/\x7/\\n/g'
foo\n
printf 'foo\n\n' | tr '\n' '\7' | sed 's/\x7/\\n/g'
foo\n\n
細節:
tr命令將每個換行符替換為\x07sed命令將每個替換\x07為\\n
uj5u.com熱心網友回復:
您可以(我認為)使用純 POSIX shell 來做到這一點。我假設您正在使用文本,而不是可以包含空位元組的任意二進制資料。
magic () {
while read x; do
printf '%s\\n' "$x"
done
printf '%s' "$x"
}
read假定 POSIX 文本行(以換行符結尾),但它仍然填充x它讀取的任何內容,直到沒有看到換行符時輸入結束。因此,只要read成功,您就可以寫回正確的行(減去換行符)x,但使用文字\n而不是換行符。
一旦回圈中斷,x在 failed 之后輸出任何內容(如果有的話) read,但沒有尾隨文字\n。
$ [ "$(printf foo | magic)" = foo ] && echo passed
passed
$ [ "$(printf 'foo\n' | magic)" = 'foo\n' ] && echo passed
passed
$ [ "$(printf 'foo\n\n' | magic)" = 'foo\n\n' ] && echo passed
passed
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/410235.html
標籤:
