簡體   English   中英

python正則表達式替換匹配組

[英]python regular expression substitution with matched group

我正在嘗試替換AndroidManifest.xml的頻道名稱,以批量生成一組要發布的頻道apk包。

xml文件中的<meta-data android:value="CHANNEL_NAME_TO_BE_DETERMINED" android:name="UMENG_CHANNEL"/>

通道配置保存在配置文件中,例如:

channel_name    output_postfix  valid 
"androidmarket" "androidmarket" true

這是我嘗試過的:

manifest_original_xml_fh = open("../AndroidManifest_original.xml", "r")
manifest_xml_fh = open("../AndroidManifest.xml", "w")
pattern = re.compile('<meta-data\sandroid:value=\"(.*)\"\sandroid:name=\"UMENG_CHANNEL\".*')
for each_config_line in manifest_original_xml_fh:
    each_config_line = re.sub(pattern, channel_name, each_config_line) 
    print each_config_line

它將整個<meta-data android:value="CHANNEL_NAME_TO_BE_DETERMINED" android:name="UMENG_CHANNEL"/>androidmarket ,這顯然不是我的需要。 然后我發現問題是pattern.match(each_config_line)返回一個匹配結果,結果組之一是“ CHANNEL_NAME_TO_BE_DETERMINED”。 我也嘗試提供一些替換實現功能,但仍然失敗。

因此,既然我已經成功找到了模式,那么如何正確替換匹配的結果組元素?

我建議采用另一種方法:將xml保存為模板,並使用標准Python字符串操作替換占位符。

例如

AndroidManifest_template.xml:

<meta-data android:value="%(channel_name)s" android:name="UMENG_CHANNEL"/>

python:

manifest_original_xml_fh = open("../AndroidManifest_template.xml", "r")
manifest_xml_fh = open("../AndroidManifest.xml", "w")
for each_config_line in manifest_original_xml_fh:
    each_config_line = each_config_line % {'channel_name': channel_name}
    print each_config_line

要僅捕獲元數據標記的值,您需要更改正則表達式:

<meta-data\sandroid:value=\"([^"]*)\"\sandroid:name=\"UMENG_CHANNEL\".*

具體來說,我更改了這一部分:

\\"(.*)\\" -這是一個貪婪的匹配,因此只要表達式的其余部分匹配,它將繼續匹配盡可能多的字符

\\"([^"]*)\\" -將匹配所有不是雙引號的內容。匹配結果仍將在第一個捕獲組中

如果您要執行替換操作,一個更好的主意可能是捕獲要保持不變的內容-我不是python專家,但是類似的事情可能會起作用:

re.sub(r'(<meta-data\sandroid:value=\")[^"]*(\"\sandroid:name=\"UMENG_CHANNEL\".*)'
, r'\1YourNewValue\2', s)

\\1是反向引用1-即它獲取第一個捕獲組匹配的對象

我認為您的誤解是,已匹配的所有內容都將被替換。 如果要保留模式中的內容,則必須捕獲它並將其重新插入替換字符串中。

或通過使用環視斷言僅匹配您要替換的內容

嘗試這個

pattern = re.compile('(?<=<meta-data\sandroid:value=\")[^"]+')
for each_config_line in manifest_original_xml_fh:
    each_config_line = re.sub(pattern, channel_name, each_config_line)

(?<=<meta-data\\sandroid:value=\\")是肯定的后置斷言,它確保此文本在之前,但不匹配(因此將不會被替換)

然后[^"]+會匹配非"

在Regexr上查看

暫無
暫無

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

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