sed:全域替換時忽略前導空格

sed:全域替換時忽略前導空格

我正在嘗試編寫一個 sed 命令來替換文件中的過多空格。每個單字之間只能有一個空格,但前導空格和製表符應單獨保留。所以文件:

     This is     an indented      paragraph. The   indentation   should not be changed.
This is the     second   line  of the    paragraph. 

會變成:

     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

我嘗試過的變體

/^[ \t]*/!s/[ \t]+/ /g

任何想法,將不勝感激。

答案1

$ sed 's/\>[[:blank:]]\{1,\}/ /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

我使用的表達式匹配一個或多個[[:blank:]](空格或製表符)一句話之後,並將它們替換為一個空格。匹配\>單字字元和非單字字元之間的零寬度邊界。

這是使用 OpenBSD 的本機測試的,但我認為它也sed應該適用於 GNU 。 sedGNUsed也用於\b匹配單字邊界。

您也可以sed -E將其縮短為

sed -E 's/\>[[:blank:]]+/ /g' file

同樣,如果\>GNU 不適用於您sed,請改用\b


請注意,雖然上面以正確的方式對範例文字進行了排序,但它並沒有相當用於刪除標點符號後的空格,如第一個句子之後

     This is     an indented      paragraph.        The   indentation   should not be changed.
This is the     second   line  of the    paragraph.

為此,一個稍微複雜的變體就可以解決問題:

$ sed -E 's/([^[:blank:]])[[:blank:]]+/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

這會將任何非空白字元後面跟著一個或多個空白字元替換為非空白字元和一個空格。

或者,使用標準sed(以及一個非常小的最佳化,因為它只會在存在時被替換兩個或更多非空格/製表符之後的空格/製表符),

$ sed 's/\([^[:blank:]]\)[[:blank:]]\{2,\}/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

答案2

POSIXly:

sed 's/\([^[:space:]]\)[[:space:]]\{1,\}/\1 /g; s/[[:space:]]*$//'

它將非空白後面的一個或多個空白字符的任何序列替換為該非空白和一個 SPC 字符,並刪除尾隨空白字符,這將覆蓋空白行和帶有尾隨空白的行(包括在來自Microsoft 文本文件的行尾)。

相關內容