태그를 기반으로 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하고 쉘 스크립트 루프에서 출력을 처리합니다.

xmlstarlet select 여러 경로 이름을 입력으로 허용하므로 {} +보다 효율적인 s 변형과 함께 사용할 수 있습니다.find-exec 피연산자. 항상 true로 평가 되므로 -exec … {} +0이 아닌 종료 상태에서 중단되지 않습니다. 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첫 번째 입력 파일의 루트 요소에 있는 네임스페이스 정의(및 사전 정의된 EXSLT의 네임스페이스)를 사용하여 xsl참조 saxon되는 다른 모든 네임스페이스는 -N옵션을 사용하여 정의 해야 합니다.
  • 변수는 또는 요소에서 구문(속성 값)을 tag1nodes수집합니다 .tag1divspan추정기본 네임스페이스 또는 비어 있는 동일한 위치에 위치
  • EXSLTdyn:maptag1cvt이 함수는 인수(텍스트 문자열로 제공된 XPath 표현식)를 평가하여 각 구문을 문자열에 매핑합니다.
  • EXSLTset:distinct중복 제거
  • 정렬 순서는 A오름차순, T확장, 지정되지 않은 케이스 순서 입니다.
  • tag1해당 값이 없으면 출력이 생성되지 않습니다. (이 경우 1이 반환됩니다 select.)
  • -C사용할 -tXSLT 1.0 스타일시트를 나열하는 옵션을 추가하기 전에select
  • 여기에 정의는 --var가독성을 위해 추가되었으며 dyn:map매개변수 로 쉽게 대체될 수 있습니다.
  • 경로 이름은 find다음에서 유래합니다.추정아니요
    • '(작은따옴표) 문자로 인해알려진 오류 존재하다select
    • 공백(출력을 처리하는 쉘 스크립트가 기본값 IFS을 사용하는 경우)read

일부 샘플 출력:

./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

관련 정보