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.

  • I would like to extract pair of entries between two consecutive string "End" and do some processing on those entries iteratively. – leo195 Jul 27 '17 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 '17 at 18:21
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
  • 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 '17 at 23:47
  • I got it using sed '/^\s*$/d'. – leo195 Jul 28 '17 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 '17 at 5:08
  • also, you can avoid the need for gsub() if you use -F':|"' - and extract $3 rather than $2. – cas Jul 30 '17 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.