根据标签重命名xml文件

根据标签重命名xml文件

我有很多 xml 文件。我需要根据tag1="alpha"xml 中的特定标签(例如 )重命名每个标签。

我已经弄清楚如何根据单身的特定标签的出现。

find . -maxdepth 1 -name '*.xml' -exec /rename.sh {} \;
#!/bin/bash

tag1=$(sed 's/.*tag1="\([^"]*\).*/\1/; q' "$1")
mv -v "$1" "$tag1.xml"

问题:有些文件有多个tag1标签,例如tag1="alpha" tag1="beta" tag1="omega".对于这些文件,我还需要创建同一文件的副本,但使用其他名称,beta.xml, omega.xml

我尝试使用位置参数进行cat,但这不起作用(我是初学者)。

文件结构示例:

<root xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">

<div class="div-entry"><d:entry xmlns:d="1.0.rng" id="m_en_gbus0240000" tag1="cudgel" class="entry">
 <span class="hg x_xh0">
   <span role="text" d:syl="1" class="hw">cudg.el<d:syl/></span>
   <span prxid="cudgel_us_nv" prlexid="pron0014256.002" dialect="AmE" class="prx"> | <span d:prn="US" dialect="AmE" class="ph t_respell">ˈ;ke;je;l<d:prn/></span><span d:prn="IPA" soundFile="cudgel#_us_1" media="online" dialect="AmE" class="ph">ˈ;ke;d&#658;e;l<d:prn/></span> | </span>
 </span>
 <span class="sg">
   <span id="m_en_gbus0240000.004" class="se1 x_xd0">
     <span role="text" class="posg x_xdh">
       <span d:pos="1" class="pos">
         <span class="gp tg_pos">noun </span>
         <d:pos/>
       </span>
     </span>
     <span id="m_en_gbus0240000.005" class="msDict x_xd1 t_core">
       <span d:def="1" role="text" class="df">a short, thick stick used as a weapon<span class="gp tg_df">. </span><d:def/></span>
     </span>
     <span class="gp x_xdt tg_se1"> </span>
   </span>
   <span id="m_en_gbus0240000.008" class="se1 x_xd0">
     <span class="x_xdh">
       <span role="text" class="posg">
         <span d:pos="2" class="pos">
           <span class="gp tg_pos">verb </span>
           <d:pos/>
         </span>
         <span class="infg"><span class="gp tg_infg">(</span><span tag1="cudgels", <span tag1="cudgeling"<span class="pr"/>, <span tag1="cudgeled"<span class="pr"/>; <span class="lg"><span class="ge">British </span></span><span tag1="cudgels", <span tag1="cudgelling", <span tag1="cudgelled"<span class="gp tg_infg">) </span></span>
       </span>
       <span role="text" class="gg"><span class="gp tg_gg">[</span>with <span class="sy">object</span><span class="gp tg_gg">] </span></span>
     </span>
     <span id="m_en_gbus0240000.011" class="msDict x_xd1 t_core">
       <span d:def="2" role="text" class="df">beat with a cudgel<d:def/></span>
       <span role="text" class="gp tg_df">: </span>
       <span role="text" class="eg">
         <span class="ex"> they would lie in wait and cudgel her to death</span>
         <span class="gp tg_eg">. </span>
       </span>
     </span>
   </span>
   <span class="gp tg_sg"> </span>
 </span>
 <span class="subEntryBlock x_xo0 t_phrases">
   <span class="gp x_xoLblBlk ty_label tg_subEntryBlock">PHRASES </span>
   <span id="m_en_gbus0240000.022" class="subEntry x_xo1">
     <span class="x_xoh">
       <span role="text" tag1="cudgel one's brains "
       <span class="vg"><span class="gp tg_vg">(</span>also <span id="m_en_gbus0240000.037" tag1="cudgel one's brain"<span class="gp tg_vg">) </span></span>
     </span>
     <span id="m_en_gbus0240000.024" class="msDict x_xo2 t_core">
       <span role="text" class="lg">
         <span class="ge">British </span>
       </span>
       <span role="text" class="df">think hard about a problem</span>
       <span role="text" class="gp tg_df">: </span>
       <span role="text" class="eg">
         <span class="ex"> she cudgeled her brains, trying to decide what had caused such an about-face</span>
         <span class="gp tg_eg">. </span>
       </span>
     </span>
     <span class="gp x_xot tg_subEntry"> </span>
   </span>
   <span id="m_en_gbus0240000.025" class="subEntry x_xo1">
     <span role="text" tag1="take up the cudgels "
     <span id="m_en_gbus0240000.026" class="msDict x_xo2 t_core">
       <span role="text" class="df">start to defend or support someone or something strongly</span>
       <span role="text" class="gp tg_df">: </span>
       <span role="text" class="eg">
         <span class="ex"> there was no one else to take up the cudgels on their behalf</span>
         <span class="gp tg_eg">. </span>
       </span>
     </span>
   </span>
 </span>
 <span role="text" class="etym x_xo0">
   <span class="gp x_xoLblBlk ty_label tg_etym">ORIGIN </span>
   <span class="x_xo1"><span class="dg"><span class="date">Old English </span></span><span class="italic">cycgel</span>, of unknown origin<span class="gp tg_etym">.</span></span>
 </span>
</d:entry>
<div class="div-entry"><div>

</root>

答案1

为什么不使用xmlstarlet提取 tag1短语并在 shell 脚本循环中处理其输出。

xmlstarlet select 接受多个路径名作为输入,因此可以与s{} +的更有效变体一起使用find-exec 操作数。请注意,-exec … {} +始终评估为 true,因此它不会在非零退出状态下中止。要列出文件名以及 tag1转换后的短语,例如:

# shellcheck shell=sh disable=SC2016

find . -maxdepth 3 -type f -name '*.xml' -exec \
  xmlstarlet select --text -t \
    --var tag1nodes='//@tag1[name(..)="span" or name(..)="div"]' \
    --var allowchars -o 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' -b \
    --var tag1cvt -o 'translate(normalize-space(),translate(.,$allowchars,""),"_")' -b \
    -m 'set:distinct(dyn:map($tag1nodes,$tag1cvt))' \
      -s 'A:T:-' '.' \
      -f -o "${ofs:-$(printf '\t')}" -v '.' -n \
  {} +

xmlstarlet select命令注释

  • select使用第一个输入文件的根元素中的命名空间定义(并预定义xslsaxon和来自 EXSLT 的命名空间),引用的任何其他命名空间都必须使用-N选项定义
  • 变量从或元素tag1nodes收集tag1短语(属性值),此处divspan假定位于默认命名空间或空同上
  • EXSLTdyn:maptag1cvt函数通过评估参数(以文本字符串形式给出的 XPath 表达式) 将每个短语映射到字符串,其中
  • EXSLT 的set:distinct消除重复
  • 排序顺序为:A升序、T扩展、未指定大小写顺序
  • tag1如果未找到相关值,则不会生成任何输出(在这种情况下select返回 1)
  • -C之前添加一个选项-t将列出 XSLT 1.0 样式表 select使用
  • 添加此处的定义--var是为了提高可读性,并可以轻松地替换为dyn:map参数
  • 路径名find来自假定没有
    • '(单引号)字符,由于已知错误select
    • 空格,如果处理输出的 shell 脚本使用默认IFSread

部分样本输出:

./dir-b/fum.xml cudgels
./dir-b/fum.xml take_up_the_cudgels
./fee.xml       cudgel_ones_brain
./fee.xml       cudgel_ones_brains
./fee.xml       cudgeled
./fee.xml       cudgeling
./fee.xml       cudgelled
./fee.xml       cudgelling

您发布的文件不是 XML,但xmlstarlet可以恢复其内容(省略-q列出错误):

xmlstarlet -q format -R junk > file.xml

答案2

这个问题似乎有两个独立的部分。第一个是查找所有 tag1 出现的内容。第二部分是如何使用它们来重命名您的 xml 文件。从当前帖子来看,第二部分的条件尚不完全清楚。

这只是第一部分的解决方案。

$ sed 's/tag1/\ntag1/g' input_file | sed  -n '/tag1/p' | cut -d '"' -f2
cudgel
cudgels
cudgeling
cudgeled
cudgels
cudgelling
cudgelled
cudgel one's brains 
cudgel one's brain
take up the cudgels

相关内容