我有字串:
lopy,lopy1,sym,lopy,lopy1,sym"
我希望這條線是:
lopy,lopy1,sym,lady,lady1,sym
這意味著應該替換字串 sym 之后的所有“小伙子”。所以我跑了:
echo "lopy,lopy1,sym,lopy,lopy1,sym" | sed -r 's/(.*sym.*?)lopy/\1lad/g'
我得到:
lopy,lopy1,sym,lopy,lad1,sym
使用 Perl 并不是更好:
echo "lopy,lopy1,sym,lopy,lopy1,sym" | perl -pe 's/(.*sym. ?)lopy/${1}lad/g'
產量
lopy,lopy1,sym,lad,lopy1,sym
并非所有的“lopy”都被替換。我究竟做錯了什么?
uj5u.com熱心網友回復:
的(.*sym.*?)lopy/(.*sym. ?)lopy圖案大致相同,. ?比換行符字符之外的一個或更多個字符相匹配,但盡可能少,并且.*?匹配零個或更多個這樣的字符。這種心態sed不支持懶惰量詞,*?是同*在sed。但是,您使用的正則運算式的主要問題是它們匹配sym,然后匹配它之后的任何文本lopy,因此,當您添加時g,它只是意味著您想找到更多的lopyafter 情況sym....lopy。并且您的字串中只有一個這樣的事件。
你想替換所有lopy之后sym,所以你可以使用
perl -pe 's/(?:\G(?!^)|sym).*?\Klopy/lad/g'
請參閱正則運算式演示。詳情:
(?:\G(?!^)|sym)-sym或上一場比賽結束 (\G(?!^)).*?- 除換行符以外的零個或多個字符,盡可能少\K- 匹配重置運算子,丟棄到目前為止匹配的所有文本lopy- 一個lopy字串。
看在線演示:
#!/bin/bash
echo "lopy,lopy1,sym,lopy,lopy1,sym" | perl -pe 's/(?:\G(?!^)|sym).*?\Klopy/lad/g'
# => lopy,lopy1,sym,lad,lad1,sym
如果值始終以逗號分隔,則可以替換.*?為,:((?:\G(?!^)|sym),\Klopy請參閱此正則運算式演示)。
uj5u.com熱心網友回復:
由于OP已經提到sed所以我在awk這里添加程式。與sed. 使用顯示的示例,請嘗試以下awk程式。
echo "lopy,lopy1,sym,lopy,lopy1,sym" |
awk -F',sym,' '
{
first=$1
$1=""
sub(/^[[:space:]] /,"")
gsub(/lop/,"lad")
$0=first FS $0
}
1
'
說明:為以上添加詳細說明。
echo "lopy,lopy1,sym,lopy,lopy1,sym" | ##Printing values and sending as standard output to awk program as an input.
awk -F',sym,' ' ##Making ,sym, as a field separator here.
{
first=$1 ##Creating first which has $1 of current line in it.
$1="" ##Nullifying $1 here.
sub(/^[[:space:]] /,"") ##Substituting initial space in current line here.
gsub(/lop/,"lad") ##Globally substituting lop with lad in rest of line.
$0=first FS $0 ##Adding first FS to rest of edited line here.
}
1 ##Printing edited/non-edited line value here.
'
uj5u.com熱心網友回復:
問題是lopy要替換的(s) 在 之后sym,具有類似 的模式sym.*?lopy,因此全域替換會尋找更多的整體sym lopy-after- sym(不僅僅是針對lopys 之后的所有s sym)。?
要替換所有lopys(在第一個之后sym,然后是另一個sym),我們可以捕獲syms 和替換側運行代碼中的子字串,其中正則運算式替換所有lopys
echo "lopy,lopy1,sym,lopy,lopy1,sym" |
perl -pe's{ sym,\K (. ?) (?=sym) }{ $1 =~ s/lop/lad/gr }ex'
為了隔離sym我\K在第一個之后使用的 s之間的子字串sym,它在它之前洗掉匹配,并且對子sym字串之后的正向前瞻,它不消耗任何東西。所述/e改性劑使作為代碼替換側進行評價。在替換方的正則運算式中,我們需要/r因為$1無法更改,我們希望正則運算式無論如何都回傳。請參閱perlretut。
? 以匹配所有的abbbb,我們不能說/ab/g,也不是/(a)b/g也不是/a(b)/g,因為那會看整個的所有重復ab的字串(并找到只ab在開頭)。
uj5u.com熱心網友回復:
sed根本不支持非貪婪通配符。但是您的 Perl 腳本也由于其他原因而失敗;您說的是“匹配所有出現的這個”,但隨后您指定了一個只能匹配一次的正則運算式。
一個常見的簡單解決方案是拆分字串,然后僅在匹配后替換:
echo "lopy,lopy1,sym,lopy,lopy1,sym" |
perl -pe 'if (@x = /^(.*?sym,)(.*)/) { $x[1] =~ s/lop/lad/g; s/.*/$x[0]$x[1]/ }'
如果你想花哨,你可以使用lookbehind來只替換lop第一個sym.
echo "lopy,lopy1,sym,lopy,lopy1,sym" |
perl -pe 's/(?<=sym.{0,200})lop/lad/'
可變長度的lookbehind 會產生一個警告,并且只在 Perl 5.30 中被支持(你可以用no warnings qw(experimental::vlb));.關閉它)
uj5u.com熱心網友回復:
由于您已經展示了一個嘗試過的sed命令和使用過的sed標簽,這里是一個sed基于回圈的解決方案:
sed -E -e ':a' -e 's~(sym,.*)lopy~\1lady~g; ta' file
lopy,lopy1,sym,lady,lady1,sym"
解釋:
:aa在匹配sym,.*模式之前設定標簽taa進行替換后將模式匹配跳轉回標簽
當s命令沒有任何匹配時,即沒有lopy子字串之后,此回圈停止sym,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/329324.html
標籤:正则表达式 perl sed 正则表达式贪婪 正则表达式替换
上一篇:我正在用Perl回圈運行neomutt。配置值來自PostgreSQL,但neomutt只讀取檔案。如何從Perl模仿檔案?
