如何 sed -e 's///' 除特定模式之外的所有內容?

如何 sed -e 's///' 除特定模式之外的所有內容?

如何用 sed 替換字串中的所有內容(除了 % 和直接緊跟其後的任何數字)?意思是,除了字串之外的所有內容,例如:

%1 %1000 %55 ETC。

給定這種形式的字串:

    1: [18x14] [history 1/2000, 268 bytes] %3
    2: [18x14] [history 1/2000, 268 bytes] %4 (active)

我只想得到%3%4零件。數字最多可達999.

答案1

$ sed 's/^.*\(%[0-9]\+\).*$/\1/' input

假設一行至多包含一個這些%123標記,且每一行都包含這樣一個標記。

\( \)字元標記一個匹配組 - 然後透過\1反向引用在替換中引用該匹配組。^/$匹配行的開頭/結尾。

否則,您可以預先過濾輸入,例如:

$ grep '%[0-9]\+' input | sed 's/^.*\(%[0-9]\+\).*$/\1/'

(當並非所有行都包含這樣的標記時)

另一種變體:

$ sed 's/\(%[0-9]\+\)/\n\1\n/g' | grep '%[0-9]'

(當一行可能包含多個這些標記時)

以下是直接在每個標記之前和之後插入的換行符號 - 在管道的第一部分中。然後該grep部分刪除所有非%123標記行。

答案2

grep -o在這種情況下你最好使用:

grep -oP '\B%[0-9]{1,3}\b' inputfile

假設您的版本grep支援 Perl 相容的正規表示式 ( -P)。否則:

grep -o '\B%[0-9]\{1,3\}\b' inputfile

使用 GNU sed,可以將空格音譯為換行符並獲得所需的行:

sed 'y/ /\n/' inputfile | sed '/^%[0-9]\{1,\}/!d'

答案3

使用時sed幾乎總是建議:

/address then/s/earch/replace/

有兩個原因。第一個是多行速度/addressing/更快 - 它僅針對尋找匹配,並且不必只選擇行的一部分進行編輯,因此它可以更快地縮小結果範圍。

第二個原因是您可以對同一地址執行多個編輯操作 - 這使事情變得更加容易。

當然,在這種情況下,僅給出您顯示的數據,這沒有實際差異。不過,這就是我會做你問的事情的方式:

sed '/^[^%]*\|[^0-9]*$/s///g' <<\DATA
    1: [18x14] [history 1/2000, 268 bytes] %3
    2: [18x14] [history 1/2000, 268 bytes] %4 (active)
DATA

#OUTPUT
%3
%4

它只是選擇所有字符非-%從行首開始的字符以及所有字符非數位的地址中行尾的字符,然後用s///- 刪除它們,就是這樣。

在當前的形式下,如果您向其提供行,它可能會以意想不到的方式破壞數據不是包含一個%digit組合 - 這就是為什麼尋址很重要。如果我們稍微改變一下:

/%[0-9]/s/[^%]*\|[^0-9]*$//g

變得更安全快點。

答案4

我的解決方案不使用 sed,而是使用具有擴展正則表達式和僅匹配選項的 grep。


$ cat file
1: [18x14] [history 1/2000, 268 bytes] %3
2: [18x14] [history 1/2000, 268 bytes] %4 (active)
$ cat file | grep -Eo '%[0-9]+'
%3
%4

在這種情況下使用 grep 比使用 sed 更簡單。

相關內容