I am a beginner in shell scripting. I wanted to know how do we grep for say two strings with AND condition within a block if the strings don't appear on the same line. I tried the following but they do not work for strings not in the same line:-grep 'string1.*string2\|string2.*string1' filenamegrep -P '^(?=.*pattern1)(?=.*pattern2)' filenameFor example I have an xml file with the following lines:-  <test-result    exectime=2017-07-07    result=FAILURE    isdone=TRUE    logicalname=this.is.test1    duration=10050  >    <test-case      testcasename=this.is.test.case.name1      testunit=abcd-mc      testpath=file:/this/is/the/file/path1/abcd.xml     >     </test-case>    </test-result> <test-result      exectime=2017-07-07      result=SUCCESS      isdone=TRUE      logicalname=this.is.test1      duration=10050     >    <test-case     testcasename=this.is.test.case.name1     testunit=abcd-mc     testpath=file:/this/is/the/file/path1/uvwx.xml    >   </test-case>  </test-result>Note that the 2 blocks of code within <test-result></test-result> tags differ in case of the testpath. So, I want to grep for the logicalname and the result (grep this.is.test1 AND FAILURE) and find the respective testpath for the same block.Next, once I have the testpath for the FAILURE scenario, how can I modify the file to make the result to SUCCESS for the block with the testpath that I found and the logicalname? Any pointers on how to go about it will be helpful
How to grep for 2 strings (AND condition) within a block which are not in the same line and then find something else within that same block
text processing
With having note that Parsing XML is bad practice, here is an awk solution for your question : )awk -v RS=<test-result '    /logicalname=this\.is\.test1/&&/result=FAILURE/ {    sub(FAILURE,SUCCESS)}1' RS='' infile.txtAt above, we are telling awk that Record Seperator RS is <test-result, then for each record will look the both PATTERNs (logicalname=this.is.test1 and result=FAILURE), if it was there (within a same block) then change FAILURE to SUCCESS from given infile.txtAs we talked in comments since you want to change specific block with testpath=...., you can add another 3rd condition to the command only. below will change only if testpath=file:/this/is/the/file/path1/abcd.xml also seen.note that you need to escape /, and better to escape .s as well.awk -v RS=<test-result '  /logicalname=this\.is\.test1/&&/result=FAILURE/&&/testpath=file:\/this\/is\/the\/file\/path1\/abcd\.xml/    {sub(FAILURE,SUCCESS)}1' RS='' infile.txt