sed 模式空間與保持空間

sed 模式空間與保持空間

我剛剛經歷過這個,但我無法理解。

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.

其中 cat 檔案是:

 foo
 foo
 bar

為什麼會這樣,1!H因為對我來說1h覆蓋了模式空間並且1!H沒有用

但 sed oneliner 似乎工作正常。

答案1

@manatwork 的回答的實際原因1h;1!H,但我想添加一個可移植性說明。

標準且可移植的語法應該是:

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\
blub/p;}'

否則它在大多數實作中都無法運作sed,例如傳統的 Unix 實作。

這是\n在命令的左側可以理解的s,但是您必須在右側使用反斜杠字符,後跟實際的換行符。您還需要命令 和;之間有,並且 之前沒有空格。s}p

您也可以將文件的內容儲存在模式空間而不是保留空間:

sed -n '
  :1
  $!{
   N;b1
  }
  s/foo\nbar/blah\
blup/p'

但對於模式和保存空間來說,大多數sed實作只能處理小文件,因為大多數非 GNU 實作對這些文件的大小都有限制(POSIX 僅要求它們能夠保存 8kiB 的資料)。

可移植的是,你最好使用perl

perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'

perl因為GNU中的大小不受限制sed,但請注意,它可能會影響系統的效能,因為如果您沒有對每個進程的記憶體使用進行管理設定限制,它最終可能會使用所有系統記憶體。

答案2

為什麼有 1!H 因為對我來說 1h 會覆蓋模式空間並且 1!H 沒有用

不會發生覆蓋,因為它們不是在同一輸入行上執行:

1h   # when input line number is 1, copy pattern space to hold space
1!H  # when input line number is not 1, append pattern space to hold space

這是必要的,因為根據info sed

`H'
     Append a newline to the contents of the hold space, and then
     append the contents of the pattern space to that of the hold space.

因此,如果您僅使用H附加所有行,則第一行之前會有一個額外的換行符:

bash-4.2$ seq 3 | sed -n 'H; ${g; p;}'

1
2
3
bash-4.2$ seq 3 | sed -n '1h; 1!H; ${g; p;}'
1
2
3

相關內容