我剛剛經歷過這個,但我無法理解。
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