0

I have a file to process and get some entries from it. The file format is:

Example Input:

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

Script will iterate and try to find String1 and print it, if String2 also present in that block append it to String1 and print.

Example Output:

Hello World
HelloAgain
NewEntry Foo

I need to loop through every such block.What I mean by a block here is content between every "End" string. I have a script like:

    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

This code works fine but the processing in between these blocks can become more complex, whats the best way to iterate such blocks and process those block entries.

NOTE:The file is kind of a property file.

2
  • I would like to extract pair of entries between two consecutive string "End" and do some processing on those entries iteratively.
    – leo195
    Jul 27, 2017 at 18:20
  • Show example input and example output please, so that we can see what your actual intent is, rather than a script that doesn't quite fit your needs.
    – DopeGhoti
    Jul 27, 2017 at 18:21

2 Answers 2

0

Given your provided input and requested output:

$ awk -F: '$0 == "End" { printf "\n" } $1 ~ /^String[12]$/ { gsub( /\"/, "", $2 ); printf( "%s ", $2)}' input
Hello World
HelloAgain
NewEntry Foo
4
  • This works phenomenal.Great!!!!!!! And if some of these lines doesn't have any of matching String then a blank line is printed. How do I avoid that?
    – leo195
    Jul 27, 2017 at 23:47
  • I got it using sed '/^\s*$/d'.
    – leo195
    Jul 28, 2017 at 0:19
  • this would print String2 lines even if String1 is not present in the block. my reading of the Q is that String2 should only be printed if it is also in the block (i.e. as well as String1, but not if by itself).
    – cas
    Jul 30, 2017 at 5:08
  • also, you can avoid the need for gsub() if you use -F':|"' - and extract $3 rather than $2.
    – cas
    Jul 30, 2017 at 5:20
0
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

This perl script uses either : or " as the field separator, to avoid the need to strip double-quotes from the output. this means we need to extract the third field rather than the second as there is now an empty field between the first : and the ". Perl arrays are zero-based, so that's $F[2].

It only prints the output for a record ("block") if there is something to print, either String1 by itself or String1 and String2 are present - i.e. it doesn't print blank lines for non-matching records.

Here's the same algorithm in awk:

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .