уменьшить вдвое числовые поля выше 10000, отбрасывая десятичные дроби

Usefuser -m /path/to/folder 2>/dev/null(descarta stderrde la salida )o examine los casos de uso disponibles conman fuser

0
03.08.2016, 19:04
3 ответа

Предполагая, что XML имеет правильный корневой тег, используя XMLStarlet:

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

Бит //VALUE выберет любой VALUE узел в XML. Бит /@PERCENT выберет атрибут PERCENT. С помощью [. > 10000] я ограничиваю выбор теми атрибутами PERCENT, значения которых превышают 10000. edit заключается в применении функции 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>
3
29.04.2021, 00:11

Если у вас нет ограничений на реализацию, то в 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 можно изменить на все, что захотите.

1
29.04.2021, 00:11

Попробуйте это в 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 " "
    }
}' $*
-2
29.04.2021, 00:11

Теги

Похожие вопросы