PERCENT=""
위 필드 안의 숫자 값을 절반으로 줄이고 싶습니다 10000
. 이 숫자에는 소수점 이하 자릿수도 있을 수 없습니다. 예를 들어 PERCENT="50001" would need to be PERCENT="25001" or PERCENT="25000"
(내 예에서는 25001이 사용되었지만 중요하지 않습니다). 모든 데이터도 한 줄에 있으므로 그 상태를 유지해야 합니다. 아래 예
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="13" ITEM_ID="0" AMOUNT="6500" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="11250" ITEM_ID="31" AMOUNT="1" GROUPING="3" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="7000" ITEM_ID="165" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="47500" ITEM_ID="167" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="10" ITEM_ID="179" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="20" ITEM_ID="179" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="60" ITEM_ID="180" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="12223" ITEM_ID="180" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="50001" ITEM_ID="206" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="2000" ITEM_ID="273" AMOUNT="1" GROUPING="1" DROPSET="0" ZONELEVEL="GSP" VER="200" />
결과는 다음과 같습니다
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="13" ITEM_ID="0" AMOUNT="6500" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="5625" ITEM_ID="31" AMOUNT="1" GROUPING="3" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="7000" ITEM_ID="165" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="23750" ITEM_ID="167" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="10" ITEM_ID="179" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="20" ITEM_ID="179" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="60" ITEM_ID="180" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="6112" ITEM_ID="180" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="25001" ITEM_ID="206" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200" /><VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="2000" ITEM_ID="273" AMOUNT="1" GROUPING="1" DROPSET="0" ZONELEVEL="GSP" VER="200" />
답변1
XML에 올바른 루트 태그가 있다고 가정하면 다음을 사용하십시오.XML 스타:
$ xml ed -u '//VALUE/@PERCENT[. > 10000]' -x 'floor(. * .5)' data.xml
이 비트는 XML의 모든 노드를 //VALUE
선택합니다 . VALUE
그들은 /@PERCENT
자신의 속성을 선택할 것입니다 PERCENT
. 값이 10,000을 넘는 속성 [. > 10000]
으로 선택을 제한 합니다 PERCENT
.편집하다floor(. * .5)
선택한 값(0.5를 곱하고 반내림) 에 함수를 적용하는 것입니다 . 여기서는 .
이전과 마찬가지로 값에 대한 자리 표시자입니다.
이것이 당신에게 줄 것입니다
<?xml version="1.0"?>
<root>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="13" ITEM_ID="0" AMOUNT="6500" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="5625" ITEM_ID="31" AMOUNT="1" GROUPING="3" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="7000" ITEM_ID="165" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="23750" ITEM_ID="167" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="10" ITEM_ID="179" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="20" ITEM_ID="179" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="60" ITEM_ID="180" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="6111" ITEM_ID="180" AMOUNT="1" GROUPING="0" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="25000" ITEM_ID="206" AMOUNT="1" GROUPING="2" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
<VALUE MON_ID="10100" START_LV="1" END_LV="99" PERCENT="2000" ITEM_ID="273" AMOUNT="1" GROUPING="1" DROPSET="0" ZONELEVEL="GSP" VER="200"/>
</root>
답변2
구현에 제한이 없다면 Perl에서는 쉽습니다.
perl -p -e 's/PERCENT="(\d{5,})"/sprintf "PERCENT=\"%d\"",int($1\/2)/eg'
e
패턴 에 추가된 것은 s/../../
Perl에게 간단한 대체를 수행하는 대신 명령 세트로 두 번째 부분을 "실행"하도록 지시합니다.
이는 g
"첫 번째 문자열뿐만 아니라 발견된 모든 문자열에 대해 이 작업을 수행"한다는 의미입니다. 따라서 원본 데이터에는 다음이 있습니다.
PERCENT="13"
PERCENT="11250"
PERCENT="7000"
PERCENT="47500"
PERCENT="10"
PERCENT="20"
PERCENT="60"
PERCENT="12223"
PERCENT="50001"
PERCENT="2000"
결과는 다음과 같습니다.
PERCENT="13"
PERCENT="5625"
PERCENT="7000"
PERCENT="23750"
PERCENT="10"
PERCENT="20"
PERCENT="60"
PERCENT="6111"
PERCENT="25000"
PERCENT="2000"
(숫자 중 두 개는 반올림으로 인해 결과와 다릅니다. 귀하의 질문에 따르면 이 경우에는 신경 쓰지 않아도 됩니다.)
이것은 약간의 속임수입니다. 10000보다 큰 숫자는 5자리 이상이어야 하므로 해당 숫자를 검색하고 찾은 값을 원래 값의 절반으로 바꿉니다.
이제 임의의 숫자를 자르려면 보다 엄격한 테스트를 위해 이를 약간 수정할 수 있습니다.
perl -p -e 's/PERCENT="(\d+)"/$x=$1; $x=int($x\/2) if $x>=10000; "PERCENT=\"$x\""/eg'
여기서는 테스트를 $x>=10000
원하는 대로 변경할 수 있다는 것이 더욱 명확해졌습니다.
답변3
Bash에서 이것을 시도해보세요:
awk '
{
for (i=1;i<=NF;i++) {
split($i,perc,"\"")
if ($i ~ "PERCENT" && perc[2] >= 10000)
printf "%s\"%d\" ", perc[1], perc[2]/2
else
printf $i " "
}
}' $*