Инкрементные XML-файлы с ударом

Это - идеальный вариант использования для утилиты pee.

./runme.sh | pee "grep ook >> ook.out" "grep eek >> eek.out"

В Debian и производных, pee найден в moreutils пакет.

0
07.12.2012, 23:46
3 ответа

поместите этот сценарий в файл (исключая: 'increase.awk'):

BEGIN { i = 1 }
/.*<process>value=""<\/process>.*/ { split($0, a, "value=\"\"") ; print a[1] "value=\"" i++ "\"" a[2] ; next }
/.*/ { print $0 }

и затем вызов:

gawk -f increase.awk < yourinputfile

объяснение: в awk, split("string", a, "separatorstring") разделяет "строку" на массив, названный a, с помощью "separatorstring" как разделитель. Так [1] содержит все, пока 1-й "separatorstring", затем [2] не содержит все до конца строки или до следующего "separatorstring", и т.д.

1
28.01.2020, 02:53
  • 1
    , конечно, необходимо будет отредактировать это, если некоторые строки файла Вы попытаетесь отредактировать, мог бы содержать части строк, используемых для обнаружения, где вставить счетчик... (исключая: Ваш сценарий может содержать закомментированные строки с такими строками?) –  Olivier Dulac 08.12.2012, 03:38
  • 2
    и Ваш пример предположили, что существует только один из тех, которые на строке, но если у Вас должны быть более сложные случаи, можно просто предварительно рассматривать файл, чтобы временно иметь один на строки, затем соединить строки назад в случае необходимости. (для этого предварительно ожидайте и добавьте <обрабатывают...../процесс> с, "начинают" и "заканчивают", и помещают новые строки прежде и после тех и возвращаются, после того как этот новый файл был отредактирован awk сценарием. –  Olivier Dulac 08.12.2012, 03:48

Вы заметили, Вы вернулись логика if-then-else конструкции когда Вы повторное голосование сценарий

отметьте размещение строк, прокомментированных с line1 и line2 ниже. У Вас были они инвертированный в Вашем переписанном коде

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '' ]]; then
           echo "value=\"$((i++))\""   # line 1 ***************
        else
           echo "$line"                # line 2 ***************
        fi
    done 3 "$file.xml"
done 
0
28.01.2020, 02:53
  • 1
    Да я очень знаю об этом. Если Вы читаете ниже демонстрационного сценария, он говорит, что то, когда это, работало, он удаляет последний тег. –  DᴀʀᴛʜVᴀᴅᴇʀ 10.12.2012, 19:44

Пожалуйста, не делайте XML так. Подумайте, если хотите - XML ​​- это структурированный тип данных, который активно игнорирует пробелы. Имеет унарные теги, такие как и другие вещи, которые означают, что если вы проанализируете его построчно, с помощью регулярных выражений однажды ваш код загадочным образом сломается.

Это можно сделать с помощью анализатора XML. Какой из них использовать - дело вкуса, но для написания сценариев мне нравится XML :: Twig (модуль perl).

Чтобы решить вашу проблему, как описано:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

sub increment_value {
    my ( $twig, $process ) = @_;
    my ($value) = ( $process->text =~ m/(\d+)/ );
    print "Got $value\n";
    if ( defined ( $value ) ) { 
        $process->set_text( 'value="' . ++$value . '"' );
    } 
    else {
        $process -> delete;
    }
}

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented',
    'twig_handlers' => { 'process' => \&increment_value },
);
$twig->parsefile( 'your_file.xml'  );
$twig->print;    #prints to stdout.

Это вызывает «обработчик» для каждого элемента process , который извлекает, преобразует и заменяет текст.

0
28.01.2020, 02:53

Теги

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