簡體   English   中英

使用sed替換不在行尾的開頭的模式

[英]Use sed to replace patterns that are not at the start of end of lines

假設我輸入了:

/a/b/c/d/e/
/a/b/c/d/e
a/b/c/d/e/
a/b/c/d/e

我想用+代替不在邊緣的所有/ ,所以輸出為:

/a+b+c+d+e/
/a+b+c+d+e
a+b+c+d+e/
a+b+c+d+e

我已經嘗試過以下命令:

sed -e "s#\(.\)/\(.\)#\1+\2#g"

這很接近但不完全是:

/a+b/c+d/e/
/a+b/c+d/e
a+b/c+d/e/
a+b/c+d/e

大概是因為\\(.\\)在連續的/字符之間重疊。

我不認為sed在行首或行尾有空匹配運算符。 那么,這是怎么做的呢?

您可以將所有斜杠轉換為+ ,然后用斜杠替換+(在開頭或結尾):

sed 'y/\//+/;s/^+\|+$/\//g;'

或如果OR運算符不可用:

sed 'y/\//+/;s/^+/\//;s/+$/\//;'

如果更改定界符以避免轉義所有文字斜杠,則更好:

sed 'y~/~+~;s~^+\|+$~/~g;'

或如果OR運算符不可用:

sed 'y~/~+~;s~^+~/~;s~+$~/~;'

(其中^是該行開頭的錨點, $是該行的結尾)


其他方式:您可以使用占位符保護要保留的斜杠:

sed 's~^/~{`%{~;s~/$~{`%{~;y~/~+~;s~{`%{~/~g;'

如果您有perl ,則可以使用環視方法:

perl -pe 's~(?<!^)/(?!$)~+~g' file

輸出:

/a+b+c+d+e/
/a+b+c+d+e
a+b+c+d+e/
a+b+c+d+e

否則,您可以將此sed與2個替代品一起使用:

sed -r 's~(.)/(.)~\1+\2~g; s~(.)/(.)~\1+\2~g' file

或者用標簽和循環來實現:

sed -r ':a;s|(.)/(.)|\1+\2|g;ta' file

這是一個sed命令,可提供您的輸出:

sed -r 's=(.)/\b=\1+=g;' file
  • 通常/用作s命令的分隔符,但這里我們使用=
  • /匹配在前面有( . )且我們位於單詞邊界的地方
  • 最初我嘗試了(.)/(.)但是沒有用:
    • 第二個點被消耗了,下一場比賽只會在第二個點之后開始,
    • 即在x/y/< ,第二個匹配項只會顯示/z而不是y/z
    • 使用\\b ,第一個匹配項不會消耗y ,第二個匹配項會看到y/

這是完成以下工作的常見且極為有用的sed習慣用法:

$ sed 's:a:aA:g; s:^/\|/$:aB:g; s:/:+:g; s:aB:/:g; s:aA:a:g' file
/a+b+c+d+e/
/a+b+c+d+e
a+b+c+d+e/
a+b+c+d+e

第一個子將所有a更改為aA 在這一點上,輸入中沒有字母a ,后跟字母A (我們需要首先執行此操作,以確保在第二個子之后,輸入中僅有的aB是該第二個子的結果)

第二個子句將行的開頭或結尾的全部/ s更改為aB 在那一點上,輸入中唯一的aB是行的開始或結尾處最初存在/ s的位置。

第3個子項將所有剩余的/ s(即不在行首或末尾的/ s)更改為+ s。

的第四子恢復aB的背部到原來的前/結束/秒。

第五個子將aA s恢復為原始a s。

這可能對您有用(GNU sed):

sed ':a;s/\([^\/]\)\/\([^\/]\)/\1+\2/g;ta' file

或在視覺上更容易:

sed -r ':a;s#([^/])/([^/])#\1+\2#g;ta' file

兩次確實是相同的正則表達式:

sed 's/\([^\/]\)\/\([^\/]\)/\1+\2/g;s/\([^\/]\)\/\([^\/]\)/\1+\2/g' file

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM