divide os campos numéricos acima de 10000, eliminando decimais

0

Eu quero reduzir para metade o valor dos números dentro do campo PERCENT="" que estão acima de 10000 . Os números também não podem ter casas decimais. Por exemplo, PERCENT="50001" would need to be PERCENT="25001" or PERCENT="25000" (usei 25001 no meu exemplo, mas realmente não importa). Todos os dados também estão em uma linha e precisam permanecer assim. Exemplo abaixo

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

Os resultados devem se parecer com

<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" />
    
por Rarara221 02.08.2016 / 15:34

3 respostas

3

Supondo que o XML tenha uma tag raiz adequada, usando XMLStarlet :

$ xml ed -u '//VALUE/@PERCENT[. > 10000]' -x 'floor(. * .5)'  data.xml

O bit //VALUE selecionará qualquer nó VALUE no XML. O /@PERCENT selecionará seu atributo PERCENT . Com [. > 10000] I restringir a seleção aos atributos PERCENT cujos valores excedam 10000. A edição é aplicar a função floor(. * .5) aos valores selecionados (multiplicar por 0,5 e arredondar para baixo), em que . , como antes, é o marcador para o valor.

Isso vai te dar

<?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>
    
por 02.08.2016 / 16:17
1

Se você não tem restrições sobre a implementação, isso é muito fácil no perl:

perl -p -e 's/PERCENT="(\d{5,})"/sprintf "PERCENT=\"%d\"",int($1\/2)/eg'

O e adicionado ao padrão s/../../ diz ao perl para "executar" a segunda parte como um conjunto de comandos, em vez de fazer uma substituição simples.

O g significa "faça isso para todas as cadeias encontradas, não apenas para a primeira" Então, nos seus dados originais você tinha:

PERCENT="13"                               
PERCENT="11250"
PERCENT="7000"
PERCENT="47500"
PERCENT="10"
PERCENT="20"
PERCENT="60"
PERCENT="12223"
PERCENT="50001"
PERCENT="2000"

Nos resultados que temos agora:

PERCENT="13"
PERCENT="5625"
PERCENT="7000"
PERCENT="23750"
PERCENT="10"
PERCENT="20"
PERCENT="60"
PERCENT="6111"
PERCENT="25000"
PERCENT="2000"

(dois dos números são diferentes do seu resultado, porque isso é um problema; sua pergunta diz que você não se importa nesse caso).

Isso é um pouco trapaceiro; um número > = 10000 deve ter 5 dígitos ou mais, então procuramos por eles e substituímos o valor encontrado por metade do original.

Agora, se quisermos cortar qualquer número arbitrário, podemos modificá-lo um pouco para um teste mais rigoroso:

perl -p -e 's/PERCENT="(\d+)"/$x=$1; $x=int($x\/2) if $x>=10000; "PERCENT=\"$x\""/eg'

Está mais claro aqui; o teste $x>=10000 pode ser alterado para o que você quiser.

    
por 02.08.2016 / 15:51
-2

Tente isso no 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 " "
    }
}' $*
    
por 03.08.2016 / 15:26