簡體   English   中英

如何刪除或替換兩個xml標簽之間的特定字符[linux,python,lxml,sed,awk,...]?

[英]how to remove or replace specific chars are between two xml tags [linux, python, lxml, sed, awk,…]?

我在python中使用LXML庫進行XML解析。

在XML文件中,我有一些不良字符導致python中出現以下錯誤:

lxml.etree.XMLSyntaxError:CharRef

在python中打開並獲取XML文件的內容之前,我必須從兩個標記中刪除不良字符:

1: <essid cloaked="true">....</essid><essid cloaked="false">....</essid>

2: <client-manuf>....</client-manuf>

XML文件的大小很大。 所以我想用sed或awk或類似工具來做。

    <crypt>0</crypt>
        <total>20    50</total>
        <fragments>0</fragments>
        <retries>0</retries>
    </packets>
    <datasize>0</datasize>
    <wireless-client number="1" type="established" first-time="Thu Feb 15 16:45:43 2018" last-time="Thu Feb 15 16:45:43 2018">
        <client-mac>08:EA:40:D0:55:43</client-mac>
        <client-manuf>SHENZHEN BILIAN ELECTRONIC CO.&#x  ef;&#x  bc;&#x  8c;LTD</client-manuf>
        <essid cloaked="true">&#x   0;&#x   0;&#x   0;&#x   0;&#x   0;</essid>
        <channel>8</channel>
        <maxseenrate>1.000000</maxseenrate>
        <carrier>IEEE 802.11b+</carrier>
        <encoding>CCK</encoding>
        <packets>
            <LLC>0</LLC>
            <data>0</data>
            <crypt>0</crypt>

我想從這些標簽中刪除壞字符(client-manuf和essid)。

來自: <client-manuf>SHENZHEN BILIAN ELECTRONIC CO.&#x ef;&#x bc;&#x 8c;LTD</client-manuf>

致(或本): <client-manuf>SHENZHEN BILIAN ELECTRONIC CO. LTD</client-manuf>

致(或本): <client-manuf>SHENZHEN BILIAN ELECTRONIC CO</client-manuf>

-----------------------------------------------

來自: <essid cloaked="true">&#x 0;&#x 0;&#x 0;&#x 0;&#x 0;</essid>

來自: <essid cloaked="false">&#x 0;&#x WiFi 0;&#x MTN 0;&#x 0;&#x 0;</essid>

To(或this): <essid cloaked="true"></essid>

To(或this): <essid cloaked="true">N/A SSID</essid>

To(或this): <essid cloaked="false">WiFi MTN</essid>

for example, two bad chars:

1: 0;

2: &#x

這是我的解決方案。 但它不能很好地滿足我的需求:

sed -e '/<essid cloaked="\\(true\\|false"\\)>*.*<\\/essid>/ s/\\(&#x\\|0;\\)//g' a.txt

使用etree.XMLParser對象的正確方法( lxml.etree ):

import re
from lxml import etree

tags_to_fix = ['clientssss-manuf', 'client-manuf', 'essid']
parser = etree.XMLParser(recover=True)   # recovery mode !
tree = etree.parse("input.xml", parser)

for el in tree.xpath('//*[name()="clientssss-manuf" or name()="client-manuf" or name()="essid"]'):
    el.text = re.sub(r'\w{1,2};\s*', '', el.text).strip()

tree.write("output.xml", encoding="utf-8", pretty_print=True)

結果output.xml的關鍵片段:

...
<packets>
<crypt>0</crypt>
        <total>20    50</total>
        <fragments>0</fragments>
        <retries>0</retries>
    </packets>
    <datasize>0</datasize>
    <wireless-client number="1" type="established" first-time="Thu Feb 15 16:45:43 2018" last-time="Thu Feb 15 16:45:43 2018">
        <client-mac>08:EA:40:D0:55:43</client-mac>
        <clientssss-manuf>SHENZHEN BILIAN ELECTRONIC CO.  LTD</clientssss-manuf>
        <client-manuf>SHENZHEN BILIAN ELECTRONIC CO.  LTD</client-manuf>
        <essid cloaked="true"></essid>
        <channel>8</channel>
        <maxseenrate>1.000000</maxseenrate>
        <carrier>IEEE 802.11b+</carrier>
        <encoding>CCK</encoding>
        <packets>
            <LLC>0</LLC>
            <data>0</data>
            <crypt>0</crypt>
</packets></wireless-client>
...

你的sed命令看起來並不那么糟糕,只留下了很多空白。

由於sed通常是貪婪的,你可以用“*”指定任意數量的空格。

cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/ s/ *\(&#x\|0;\) *//g'

另一方面,如果有一些有效的文本,您可能不想將它們粘在一起,因此您可以為每個刪除的模式添加一個空格:

cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/ s/ *\(&#x\|0;\) */ /g'

最后,您可以將多個空格壓縮為一個:

cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/{s/ *\(&#x\|0;\) */ /g;s/  */ /g}'

注意,構造{foo; bar}將兩個命令綁定到一個命令塊,僅對之前抓取的模式進行操作。 第二種模式會影響整個文件。

使用另一對蒙版括號和蒙版加:

cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/{s/\( *\(&#x\|0;\) *\)\+/ missing essid /g;s/  */ /g}'

你可以:用一個東西代替一個模式的重復出現。

      s/\( *\(&#x\|0;\) *\)\+/ missing essid /;
      ^  (   (pattern1)   )+ / replacement   /(g now obsolete
         (pattern .......2)

內部模式是替代&#x或0;。 外部圖案是內部圖案,可選擇由空白保護

     "0;"
     "0; "
     " 0; "
     " 0;"
     "    0;  "
     "    &#x"

等等。

你想要內部模式,我們稱之為X,重復一次或多次,因此+。 但是沒有parens,+只能解決最后一個字符,而不是整個模式。

你必須學習這種正則表達式語言。 找一個教程。 你不能要求在生活中需要的每一種可能的變化。

有了良好的基本理解,它會很快得到回報。 你不需要知道所有的東西,但基本的東西,應該有一個很好的估計,什么是可能的,什么不是。 然后一個回購,搜索的東西,很少使用。 然后你可能只會問困難/復雜的東西。

暫無
暫無

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

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