2016-08-31 43 views
-2

我不得不在目錄中創建一個xml文件的大約500個副本,這是我設法完成的。作爲下一個問題的一部分是我想重命名文件中的特定文本。我該怎麼去做呢?用文件名重命名多個文件中的特定實例?

這是我有: 1000.xml,1001.xml,1002.xml ...

1000.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation='test.xsd'> 
<address> 
    <name>Joe Tester</name> 
    <street>Baker street 5</street> 
    <id>1000</id> 
</address> 
<count>1000</count> 

本質上講,這被複制到所有其他文件,但以數字和按時間順序排列的名稱。如何將「1000」替換爲「文件名」?因此,新的文件應該是 - 1001.xml:

<?xml version="1.0" encoding="UTF-8"?> 
    <addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:noNamespaceSchemaLocation='test.xsd'> 
    <address> 
     <name>Joe Tester</name> 
     <street>Baker street 5</street> 
     <id>1001</id> 
    </address> 
    <count>1001</count> 
</addresses> 

我能做的只有這 - sed -i '' -e 's/1000/1001/g' $(find . -type f)這將替換所有1000 1001,而不是文件名。

+1

到目前爲止,你有什麼嘗試?這看起來像一個非常簡單的shell腳本任務。也許一個'for'循環? – larsks

+0

我發佈了我能想到的sed命令。但是它將所有1000重命名爲1001.但是,它應該是1002文件1002.xml中的1002,1003中的1003.xml等等。 – Metahuman

回答

2

破譯你的問題,我看你想改變實際內容的XML文件即ID或其他一些節點的文本文件的名稱,以便使用XML解析器像lxml

from glob import iglob 
import lxml.etree as et 

for fle in iglob("[0-9][0-9][0-9][0-9].xml"): 
    tree = et.parse(fle) 
    id_ = tree.find(".//id").text = fle 
    tree.write(fle, encoding="utf-8") 

後,如果您要更改計數也使用:

for fle in iglob("[0-9][0-9][0-9][0-9].xml"): 
     tree = et.parse(fle) 
     id_, count = tree.find(".//id"), tree.find(".//count") 
     id_.text = count.text = fle 
     tree.write(fle, encoding="utf-8") 

無論文本要設置爲文件名只尋找與發現節點並設置文本使用node.text = ...邏輯。如果你想使用的名稱忽略擴展只是拆分:

for fle in iglob("[0-9][0-9][0-9][0-9].xml"): 
     tree = et.parse(fle) 
     id_, count = tree.find(".//id"), tree.find(".//count") 
     id_.text = count.text = fle.split(".")[0] 
     tree.write(fle, encoding="utf-8") 
+0

謝謝Padraic。如何編輯id中的文件內容,計入文件名? – Metahuman

+0

@Methuman,這就是第二個片段所做的,用'tree.write(fle,encoding =「utf-8」)'跟着它,它會寫入新的數據,我編輯了答案。 –

+0

你只是想替換爲1000替換爲1001等...或使用完整的文件名? –

1

在環 -

for i in {1000..1500} #or whatever your maximum number is 
do 
sed -i "s/1000/"$i"/g" "$i".xml 
done 
+1

我真的不確定這是一個好的解決方案。它可以工作,但是......處理XML而不解析它幾乎總是很糟糕。 – Sobrique

+0

如果你知道上下文將始終包含brokets,也許可以做's /> 1000 $ i tripleee

3

試試你的sed命令您已經標記了它perl所以這裏就是我會做:

#!/usr/bin/perl 
use strict; 
use warnings; 

use XML::Twig; 
#iterate the files. 
foreach my $xml_file (glob "*.xml") { 
    #regex match the number for the XML. 
    my ($file_num) = $xml_file =~ m/(\d+).xml/; 
    #create an XML::Twig, and set it to 'indented' output. 
    XML::Twig -> new (pretty_print => 'indented', 
      #matches elements and runs the subroutine on 'it'. ($_) is the 
      #current element in this context. 
         twig_handlers => { 'address/id' => sub { $_ -> set_text($file_num) }, 
              'count'  => sub { $_ -> set_text($file_num) }, 
      #parsefile_inplace reads and writes back any changes to the file 
      #as it goes. 
             }) -> parsefile_inplace($xml_file); 


} 

這使用XML::Twig,它允許你做一個到位編輯。它通過元素處理程序執行此操作,在處理匹配時,將文件的正確數值替換爲內容。

我選擇來取代定義內容address/idcount,而不是僅僅做直接搜索和替換,因爲那樣的話......你不必擔心1000顯示出來的其他任何地方的內容。 (如地址)。

+0

謝謝!這工作! – Metahuman