簡體   English   中英

Perl 正則表達式捕獲組和重新洗牌模式

[英]Perl regex capture groups and reshuffle pattern

我使用 perl 正則表達式捕獲組來替換大量文件的模式。

文件示例 1:

title="alpha" lorem ipsum lorem ipsum name="beta"

文件示例 2:

title="omega" Morbi posuere metus purus name="delta"

為了

title="beta" lorem ipsum lorem ipsum
title="delta" Morbi posuere metus purus

使用

find . -type f -exec perl -pi -w -e 's/title="(?'one'.*?)"(?'three'.*?)name="(?'two'.*?)"/title="\g{two}"\g{three}/g;' \{\} \;

(注意(1)title和name的屬性值是未知變量,(2) title="alpha"name="beta"的內容不同。)

我還在學習 perl 正則表達式。 我究竟做錯了什么? .

這個perl命令行應該可以工作:

perl -pe 's/(title=)"?[^"\s]*"?(.*) name="?([^"\s]+)"?/$1"$3"$2/' file

title="beta" lorem ipsum lorem ipsum
title="delta" Morbi posuere metus purus

解釋:

  • (title=) : 匹配title=並在組 #1 中捕獲
  • "?[^"\s]+"? :匹配帶引號的非空格字符串
  • (.*) :匹配 0 個或多個任意字符並在組 #2 中捕獲
  • name="? : 匹配name= text 后跟可選的"
  • ([^"\s]+) :匹配引用的非空格字符串並在組 #3 中捕獲
  • "? :可選"
  • $1"$3"$2 : 替換零件

正則表達式演示

一些語法:使用(?<name>pattern)捕獲,然后在模式之外使用$+{name} (分隔符可能會有所不同,請參見perlre )。 整個正則表達式

s{ title="(?<t>[^"]+)" (?<text>.*?) name="(?<n>[^"]+)" }
 {title="$+{n}"$+{text}}x

問題中嘗試的\g{name}語法在模式本身內部使用(如果在首次捕獲它的相同模式中進一步需要它); 但是在匹配端之后,因此在替換端或正則表達式之后,可以從%+變量中檢索匹配項。

[^"]是一個否定的字符類,匹配除"之外的任何字符。 最后的修飾符/x使它忽略內部的文字空格,因此我們可以使用它們來提高可讀性。

使用上述正則表達式的完整示例,可在命令行上運行

echo title=\"alpha\" lorem ipsum lorem ipsum name=\"beta\" | perl -wpe
's{title="(?<t>[^"]+)"(?<text>.*?)name="(?<n>[^"]+)"}{title="$+{n}"$+{text}}'

(為了便於閱讀,分成兩行)。 它打印

title="beta" lorem ipsum lorem ipsum 

不確定第一個需要捕獲什么,如問題所示,但也許它比顯示的更多,因此它也被捕獲到$+{t}中。

此外,該問題相當松散地使用了這些引號。 一個命令行程序可以'分隔的字符串串在一起,但我建議不要這樣做(如果這是意圖的話)。

第一種解決方案:由於您使用的是 shell 的find命令,所以如果您對awk代碼沒問題,這里用 GNU awk編寫和測試。

這是以下代碼中使用的正則表達式的在線演示

awk -v s1="\"" '
match($0,/(title=)"[^"]*" (.*)name="([^"]*)"/,arr){
  print arr[1] s1 arr[3] s1,arr[2]
}
'  Input_file

解釋:這里的簡單解釋是使用 GNU awkmatch function; 這允許我們在其中使用正則表達式來查找所需的 output。 在這里,我使用正則表達式(title=)"[^"]*" (.*)name="([^"]*)"創建 3 個捕獲組,其值存儲到名為 arr 的數組中,並帶有索引``1,2,3 與捕獲的組值的值。 然后在打印值時,我按照 OP 的要求 output 打印它們。



第二種解決方案:sed中使用相同的正則表達式和-E (ERE) 啟用選項,請嘗試以下代碼。

sed -E 's/^(title=)"[^"]*" (.*)name="([^"]*)"/\1"\3" \2/' Input_file

暫無
暫無

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

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