Sed

sed:匹配“除換行符以外的任何字元”的攜帶式解決方案

  • September 24, 2021

我可以通過以下方式匹配換行符\n

echo "one
two" | sed 'N;s/\n/_/g'

在 GNUsed中,我可以[^\n]用來匹配除換行符以外的任何字元:

echo "one
two" | sed 'N;s/[^\n]/_/g'

這非常方便,但它違反了 POSIX。其他sed版本正確回答__n______

製表符也是如此,但我可以通過使用實際的製表符來解決問題,前面是 ctrl-v。但這不適用於換行符:

echo "one
two" | sed 'N;s/[^
]/_/g'

給我unbalanced brackets

[^[:cntrl:]]僅在沒有我想匹配的其他控製字元時使用。

那麼在 POSIX 中匹配除換行符以外的任何字元的正確方法是什麼sed

實際上有一種非常巧妙的方法可以在正常中處理這種情況sed:將換行符與一些正常字元交換,例如,_ 然後執行

$$ ^_ $$然後翻轉回來。我想發布一個問題的解決方案,但懶得發布它,但現在讓我把它放在這裡:

sed -e '
  /./!b

  :loop
     $q; N
  /\n$/bloop

  h

  /\ncreate table/!{
     s/\(.*\)\n.*/\1/p
     g;s/.*\(\n\)/\1/;D
  }

  g

  y/\n_/_\n/
     s/^[^_]*/test/
  y/\n_/_\n/

' input.data

上述解決方案的問題陳述。

基本正則表達式的 POSIX 規範不允許\n匹配文字換行符(我在下面強調):

POSIX.1-2017 的 Shell and Utilities 卷在對那些使用正則表達式的標準實用程序的單獨描述中指定了它們是否允許匹配<newline>字元;如果沒有另外說明,<newline>在模式或匹配文本中使用文字字元或任何等效的轉義序列會產生未定義的結果

幸運的是,sed實用程序的規範包含以下文本,另有說明:

sed實用程序應支持 XBD 基本正則表達式中描述的 BRE,並添加以下內容:

$$ … $$

  • 轉義序列\n應匹配<newline>嵌入在模式空間中的一個。$$ … $$

這允許使用正則表達式sed匹配嵌入在模式空間中的文字換行符(使用 eg N) 。\n

這讓我相信用它[^\n]來匹配任何單個非換行符都是可以的。這也是sedGNU 系統、OpenBSD、FreeBSD 和 Plan 9 上的實現所做的。

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