![각 패턴 일치를 제거하고 새 파일에 쓰는 방법](https://linux55.com/image/198375/%EA%B0%81%20%ED%8C%A8%ED%84%B4%20%EC%9D%BC%EC%B9%98%EB%A5%BC%20%EC%A0%9C%EA%B1%B0%ED%95%98%EA%B3%A0%20%EC%83%88%20%ED%8C%8C%EC%9D%BC%EC%97%90%20%EC%93%B0%EB%8A%94%20%EB%B0%A9%EB%B2%95.png)
그래서 모든 패턴 일치에서 제거하고 싶은 공백이 없는 긴 문자열이 있습니다. 문자열은 다음과 같습니다.
bdy11<entryunit="phoenix"><name>costperdps</name><value>27.75</value></entry><entryunit="phoenix"><name>damage</name><value>5</value></entry><entrbdy623yunit="phoenix"><name>dps</name><value>9.01</value></entry><entryunit="phoenix"><name>dpsplusbonus</name><value>18.02</value></entry><entryunit="phoenix"><name>dpsplusupgbonus</name><value>23.42</value></entry><entryunit="phoenix"><name>dpsplusupgrades</name><value>14.41</value></entry><entryunit="phoenix"><name>range</name><value></value></entry><entryunit="phoenix"><name>targets</name><value>air</value></entry><entryunit="phoenix"><name>upgrade</name><value>1</value></entry><entryunit=bdy624"phoenix"><name>upgrade_damage</name><value></value></entry><entryunit="photoncannon"><name>attack</name><value>1</value></entry><entryunit="photoncannon"><name>bonus_damage</name><value></value></entry><entryunit="photoncannon"><name>bonus_type</name><value></value></entry><entryunit="photoncannon"><name>cooldown</name><value>1.25</value></entry><entryunit="photoncannon"><name>costperdps</name><value>9.38</value></entry><entryunit="photoncannon"><name>damage</name><value>20</value><bdy625/entry><entryunit="photoncannon"><name>dps</name><value>16.00</value></entry><entryunit="photoncannon"><name>dpsplusbonus</name><value></value></entry><entryunit="photoncannon"><name>dpsplusupgbonus</name><value></value></entry><entryunit="photoncannon"><name>dpsplusupgrades</name><value>16.00</value></entry><entryunit="photoncannon"><name>range</name><value></value></entry><entryunit="photoncannon"><name>targets</name><value>both</value></entry><entryunit="photoncannon"><name>upgrbdy626ade</name><value></value></entry><entryunit="photoncannon"><name>upgrade_damage</name><value></value></entry><entryunit="probe"><name>attack</name><value>1</value></entry><entryunit="probe"><name>bonus_damage</name><value></value></entry><entryunit="probe"><name>bonus_type</name><value></value></entry><entryunit="probe"><name>cooldown</name><value>1.50</value></entry><entryunit="probe"><name>costperdps</name><value>15.00</value></entry><entryunit="probe"><name>damage</name><value>5</valubdy627e></entry><entryunit="probe"><name>dps</name><value>3.33</value></entry><entryunit="probe"><name>dpsplusbonus</name><value></value></entry><entryunit="probe"><name>dpsplusupgbonus</name><value></value></entry><entryunit="probe"><name>dpsplusupgrades</name><value>3.33</value></entry><entryunit="probe"><name>range</name><value></value></entry><entryunit="probe"><name>targets</name><value>ground</value></entry><entryunit="probe"><name>upgrade</name><value></value></entry><entryunit="probe">bdy628<name>upgrade_damage</name><value></value></entry><entryunit="sentry"><name>attack</name><value>1</value></entry><entryunit="sentry"><name>bonus_damage</name><value></value></entry><entryunit="sentry"><name>bonus_type</name><value></value></entry><entryunit="sentry"><name>cooldown</name><value>1.00</value></entry><entryunit="sentry"><name>costperdps</name><value>25.00</value></entry><entryunit="sentry"><name>damage</name><value>6</value></entry><entryunit="sentry"><name>dps</name><value>6bdy629.00</value></entry><entryunit="sentry"><name>dpsplusbonus</name><value></value></entry><entryunit="sentry"><name>dpsplusupgbonus</name><value></value></entry><entryunit="sentry"><name>dpsplusupgrades</name><value>9.00</value></entry><entryunit="sentry"><name>range</name><value></value></entry><entryunit="sentry"><name>targets</name><value>both</value></entry><entryunit="sentry"><name>upgrade</name><value>1</value></entry><entryunit="sentry"><name>upgrade_damage</name><value></value></entrbdy630y><entryunit="stalker"><name>attack</name><value>1</value></entry><entryunit="stalker"><name>bonus_damage</name><value>4</value></entry><entryunit="stalker"><name>bonus_type</name><value>armored</value></entry><entryunit="stalker"><name>cooldown</name><value>1.44</value></entry><entryunit="stalker"><name>costperdps</name><value>25.20</value></entry><entryunit="stalker"><name>damage</name><value>10</value></entry><entryunit="stalker"><name>dps</name><value>6.94</value></entry><entryunit="bdy631stalker"><name>dpsplusbonus</name><value>9.72</value></entry><entryunit="stalker"><name>dpsplusupgbonus</name><value>11.81</value></entry><entryunit="stalker"><name>dpsplusupgrades</name><value>9.03</value></entry><entryunit="stalker"><name>range</name><value></value></entry><entryunit="stalker"><name>targets</name><value>both</value></entry><entryunit="stalker"><name>upgrade</name><value>1</value></entry><entryunit="stalker"><name>upgrade_damage</name><value></value></entry><entryunit="vbdy632oidray"><name>attack</name><value>1</value></entry><entryunit="voidray"><name>bonus_damage</name><value>4</value></entry><entryunit="voidray"><name>bonus_type</name><value>armored</value></entry><entryunit="voidray"><name>cooldown</name><value>.60</value></entry><entryunit="voidray"><name>costperdps</name><value>35.00</value></entry><entryunit="voidray"><name>damage</name><value>6</value></entry><entryunit="voidray"><name>dps</name><value>10.00</value></entry><entryunit="voidray">bdy633<name>dpsplusbonus</name><value>16.67</value></entry><entryunit="voidray"><name>dpsplusupgbonus</name><value>21.67</value></entry><entryunit="voidray"><name>dpsplusupgrades</name><value>15.00</value></entry><entryunit="voidray"><name>range</name><value></value></entry><entryunit="voidray"><name>targets</name><value>both</value></entry><entryunit="voidray"><name>upgrade</name><value>1</value></entry><entryunit="voidray"><name>upgrade_damage</name><value></value></entry><entryunit="vobdy634idraycharged"><name>attack</name><value>1</value></entry><entryunit="voidraycharged"><name>bonus_damage</name><value>8</value></entry><entryunit="voidraycharged"><name>bonus_type</name><value>armored</value></entry><entryunit="voidraycharged"><name>cooldown</name><value>.60</value></entry><entryunit="voidraycharged"><name>costperdps</name><value>26.25</value></entry><entryunit="voidraycharged"><name>damage</name><value>8</value></entry><entryunit="voidraycharged"><name>dps</nbdy635ame><value>13.33</value></entry><entryunit="voidraycharged"><name>dpsplusbonus</name><value>26.67</value></entry><entryunit="voidraycharged"><name>dpsplusupgbonus</name><value>36.67</value></entry><entryunit="voidraycharged"><name>dpsplusupgrades</name><value>18.33</value></entry><entryunit="voidraycharged"><name>range</name><value></value></entry><entryunit="voidraycharged"><name>targets</name><value>both</value></entry><entryunit="voidraycharged"><name>upgrade</name><value>1<bdy636/value></entry><entryunit="voidraycharged"><name>upgrade_damage</name><value>1</value></entry><entryunit="zealot"><name>attack</name><value>2</value></entry><entryunit="zealot"><name>bonus_damage</name><value></value></entry><entryunit="zealot"><name>bonus_type</name><value></value></entry><entryunit="zealot"><name>cooldown</name><value>1.20</value></entry><entryunit="zealot"><name>costperdps</name><value>7.50</value></entry><entryunit="zealot"><name>damage</name><value>8</value></entrybdy637><entryunit="zealot"><name>dps</name><value>13.33</value></entry><entryunit="zealot"><name>dpsplusbonus</name><value></value></entry><entryunit="zealot"><name>dpsplusupgbonus</name><value></value></entry><entryunit="zealot"><name>dpsplusupgrades</name><value>18.33</value></entry><entryunit="zealot"><name>range</name><value></value></entry><entryunit="zealot"><name>targets</name><value>ground</value></entry><entryunit="zealot"><name>upgrade</name><value>1</value></entry><entryunit="zealotbdy638"><name>upgrade_damage</name><value></value></entry></record>trl000000204000001410
bdy 다음에 2자리, bdy 다음에 3자리가 나올 때마다 삭제하고 싶습니다. 지금까지 정규식과 함께 sed를 사용해 보았지만 정규식에 버그가 있다고 생각합니다.
sed 's/(.*bdy\d\d)//g; s/(.*bdy\d\d\d)//g' newTarget
파이프를 사용하여 텍스트를 변환할 계획입니다.
sed -e "
s|<tag>|\n&|
s/.*\n//
s|</tag>|&\n|
/\n/P;D
" newTarget > newTarget2
레이블 사이의 데이터를 더 쉽게 추출할 수 있도록 각 레이블을 새 줄에 배치하려면 이 작업을 수행하기 전에 bdy와 레이블 사이에 나타나는 숫자를 제거해야 합니다.
답변1
문자열을 유효한 XML로 변환하려고 한다고 가정합니다. 문자열을 제거해야 할 뿐만 아니라 태그와 해당 속성(현재 로 함께 작성됨)을 bdy
수정하고 시작 부분에 누락된 시작 태그를 추가하고 마지막 문자열을 제거해야 합니다.entry
unit
entryunit
<record>
trl
echo
다음을 사용하여 이 작업을 수행한 sed
다음 더 나은 가독성을 위해 형식을 다시 지정할 수 있습니다 xmlstarlet
.
{
echo '<record>'
sed -e 's/bdy[0-9]\{2,3\}//g' \
-e 's/entryunit/entry unit/g' \
-e 's/trl[0-9]*$//' file
} | xmlstarlet fo
아니면 한 줄로,
{ echo '<record>'; sed -e 's/bdy[0-9]\{2,3\}//g' -e 's/entryunit/entry unit/g' -e 's/trl[0-9]*$//' file; } | xmlstarlet fo
xmlstarlet
이 비트는 문서의 형식을 적절하게 다시 지정하려는 경우에만 필요합니다. 형식을 다시 지정하지 않아도 XML 파서는 여전히 문제 없이 읽을 수 있습니다.
이 sed
명령은 먼저 모든 bdy
문자열을 제거합니다. bdy
하위 문자열 뒤의 한 자리 또는 두 자리 숫자를 일치시키는 데 사용됩니다 . [0-9]\{2,3\}
이는 "0과 9 사이의 두 자리 또는 세 자리 숫자"를 의미합니다.
간단한 교체를 사용 하도록 문자열 entryunit
이 수정되었습니다 .entry unit
trl
마지막으로 교체된 문자열과 뒤따르는 숫자 문자열을 제거합니다 .
형식을 다시 지정 하면 xmlstarlet
출력은 다음과 같아야 합니다.
<?xml version="1.0"?>
<record>
<entry unit="phoenix">
<name>costperdps</name>
<value>27.75</value>
</entry>
<entry unit="phoenix">
<name>damage</name>
<value>5</value>
</entry>
[...]
<entry unit="zealot">
<name>upgrade</name>
<value>1</value>
</entry>
<entry unit="zealot">
<name>upgrade_damage</name>
<value/>
</entry>
</record>
나중에 생성된 XML 문서의 형식을 다시 지정 하는지 여부에 관계없이 xmlstarlet
도구를 사용하여 다음과 같이 데이터를 추출할 수 있습니다.
xmlstarlet sel -t -v '//entry[@unit="photoncannon" and name="cooldown"]/value' -nl file
위 출력은 속성 및 하위 노드 값이 있는 노드의 값입니다 value
. 즉, 광자포의 쿨다운 값을 얻습니다.entry
unit
photoncannon
name
cooldown
쉘 변수에서 얻은 매개변수를 사용하십시오.
unit=photoncannon
name=cooldown
xmlstrlet sel -t \
--var unit="'$unit'" \
--var name="'$name'" \
-v '//entry[@unit=$unit and name=$name]/value' -nl file
(사용된 특정 따옴표에 유의하십시오. 내부 변수는 XML로 인코딩된 문자열을 포함해야 $unit
하며 $name
, 이는 명시적인 따옴표가 필요함을 의미합니다.)
분명히 다른 XML 파서를 사용하여 동일한 작업을 수행할 수 있습니다. 다음 용도 xq
(에서여기)는 JSON 파서 위에 있는 XML 파서입니다 jq
. 즉, 먼저 XML 문서를 JSON으로 변환한 다음 jq
결과 데이터를 구문 분석하기 위해 호출합니다.
unit=photoncannon
name=cooldown
xq -r \
--arg unit "$unit" \
--arg name "$name" \
'.record.entry[] | select(."@unit" == $unit and .name == $name).value' file