Iterate over some pattern using shell

У меня есть файл, который нужно обработать и получить из него несколько записей. Формат файла такой:

Пример ввода:

String1:"Hello"
String2:"World"
String3:"Question"
End
String1:"HelloAgain"
String5:"Answer"
End
String1:"NewEntry"
String2:"Foo"
String5:"NewFile"
End

Скрипт будет выполнять итерации и пытаться найти Строку1 и вывести ее, если Строка2 также присутствует в этом блоке, добавить ее к Строке1 и вывести.

Пример вывода:

Hello World
HelloAgain
NewEntry Foo

Мне нужно просмотреть каждый такой блок. Под блоком я понимаю содержимое между каждой строкой "End". У меня есть сценарий типа:

    cat $1 | while read line
do
    if [[ $line == "String1="* ]];
    then
        string1=$line
    fi
    if [[ $line == "String2="* ]];
    then
        string2=$line
    fi
    if [[ $line == "End" ]];
    then
        if [ $string1 ];
            then
            echo "string1/"$string1"
        fi
        if [ $string1 ] && [ $string2 ];
            then
            echo $string1" "$string2
        fi
    #Reset values
    string1=''
    string2=''
    fi
done

Этот код работает хорошо, но обработка между этими блоками может стать более сложной, какой лучший способ итерации таких блоков и обработки записей этих блоков.

ПРИМЕЧАНИЕ: Файл является своего рода файлом свойств.

0
27.07.2017, 21:37
2 ответа

С учетом введенных вами данных и запрошенных выходных данных:

$ awk -F: '$0 == "End" { printf "\n" } $1 ~ /^String[12]$/ { gsub( /\"/, "", $2 ); printf( "%s ", $2)}' input
Hello World
HelloAgain
NewEntry Foo
0
28.01.2020, 04:43
perl -F':|"' -lane 'if ($out && $_ eq "End") {print "$out"; $out=""};
  $out  = $F[2] if ($F[0] eq "String1");
  $out.= $F[2] if ($out && $F[0] eq "String2")' input.txt

Этот perl-скрипт использует либо :, либо "в качестве разделителя полей, чтобы избежать необходимости удалять из вывода двойные -кавычки. это означает, что нам нужно извлечь третье поле, а не второе, поскольку теперь между первым :и "есть пустое поле. Массивы Perl основаны на нуле -, так что $F[2].

Он печатает вывод только для записи ("блока" ), если есть что печатать, либо String1 сама по себе , либо String1 и String2 присутствуют -, т.е. t печатать пустые строки для не соответствующих -записей.

Вот тот же алгоритм вawk:

awk -F':|"' 'out && $0 == "End"  { print out; out="" };
  $1 == "String1" { out=$3 };
  out && $1 == "String2" { out = out$3 }' input.txt
0
28.01.2020, 04:43

Теги

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