0

file:

string1 string2 string3 string4 string5 string6  
string3 string1 string2 string4 string5 string6  
string6 string3 string2 string4 string1 string5

expectation:

string2 string3 string4 string5  
string2 string4 string5  
string2 string4 string1 string5

Match pattern=string1
How to print match lines but only from string2 to string5 with awk ?

Unfortunately this is not processing in line :

 awk '/string2/,/string5/' file 

Let's assume there are few long lines with string2 and string5 in different places.

  • We don't do homework for you. – waltinator Mar 5 '17 at 18:12
  • @waltinator this is not a homework. Can't find solution. Incredible how easy is to judge :) – EdiD Mar 5 '17 at 18:21
  • OK, you edited the question, but you only added same comment that you posted on steeldrivers answer. This doesn't clarify at all. Please post an example of file you are working with, and the output that you want to see. See this post for example: askubuntu.com/q/867664/295286 User shows what they have, and what they want command to output – Sergiy Kolodyazhnyy Mar 5 '17 at 18:32
  • @Serg it should be clear now – EdiD Mar 5 '17 at 18:42
  • 1
    Why awk? This seems like a simple job for sed: sed 's/.*\(string2.*string5\).*/\1/' – muru Mar 6 '17 at 1:31
3

You can use awk's index and match functions e.g.

awk 'match($0,/string5/) {
  START2 = index($0,"string2");
  print substr($0,START2,RSTART+RLENGTH-START2)
}' file

Ex.

$ mawk 'match($0,/string5/) {
  START2 = index($0,"string2");
  print substr($0,START2,RSTART+RLENGTH-START2)
}' file
string2 string3 string4 string5
string2 string4 string5
string2 string4 string1 string5

Note this assumes that string2 will exist in every line in which string5 exists - if that's not the case, you will need to check the value of index($0,"string2") and act accordingly.

  • Can't do it. Let's assume there are few long lines with string2 and string5 in different places. – EdiD Mar 5 '17 at 18:26
  • 1
    @EdiD OK, please clarify your question. You need to post an actual example of text you are using so that we can work with something. Otherwise, your question is unclear. If you keep changing requirements as you go, we can't help you – Sergiy Kolodyazhnyy Mar 5 '17 at 18:27
  • @Serg question edited. – EdiD Mar 5 '17 at 18:29
  • @steeldriver OP edited his question, see updated input and output examples – Sergiy Kolodyazhnyy Mar 5 '17 at 18:50
3

Effectively,what you want to do is iterate over each field, and "enable" printing with a variable if result is found. Thus, what you need is a flag variable and for loop:

$ cat file.txt
string1 string2 string3 string4 string5 string6
string3 string1 string2 string4 string5 string6
string6 string3 string2 string4 string1 string5

$ awk '{flag=0;for(i=1;i<=NF;i++){ if($i=="string2") flag=1; if($i=="string6") flag=0;  if(flag)printf "%s%s",$i,FS;};print"";}' file.txt  
string2 string3 string4 string5 
string2 string4 string5 
string2 string4 string1 string5 

What happens here is that the whole code block will run for each line. On each line we are iterating from first field to last. Initially we set flag variable to 0, then proceed to examine each field. If field contains the desired "string2" , the flag will be set to 1, and if it is "string6" (which is the one when we want to stop) - flag will be set to 0; finally, if statement will check if flag is set and print the current field appended with field separator (represented by FS variable). After all has been printed we also insert new-line via print "" command.

In case where you have lines without match, the above command will print blank lines. You can mitigate that via adding search pattern, which will limit code-block execution only when there is pattern found in string:

$ cat file.txt
string1 string2 string3 string4 string5 string6
blah blah
string3 string1 string2 string4 string5 string6
string6 string3 string2 string4 string1 string5

$ awk '$0~"string2"{flag=0;for(i=1;i<=NF;i++){ if($i=="string2") flag=1;  if(flag)printf "%s%s",$i,FS;};print"";}' file.txt
string2 string3 string4 string5 string6 
string2 string4 string5 string6 
string2 string4 string1 string5 

Alternatively, we can use an extra variable with same result:

$ awk '{j=0;f=0;for(i=1;i<=NF;i++){if($i=="string2"){j=1;f=1};if(f)printf "%s%s",$i,FS;};if(j)print"";}' file.txt        
string2 string3 string4 string5 string6 
string2 string4 string5 string6 
string2 string4 string1 string5
  • Almost but output should be without string6 – EdiD Mar 5 '17 at 18:51
  • @EdiD yes, i noticed that. Will edit in a minute – Sergiy Kolodyazhnyy Mar 5 '17 at 18:51
  • Could you also make some explanation about printf part. – EdiD Mar 5 '17 at 18:53
  • +1 It works but prints empty lines before match. – EdiD Mar 5 '17 at 18:56
  • @EdiD do you have lines where there is no "string2" ? – Sergiy Kolodyazhnyy Mar 5 '17 at 18:58
1

Using grep:

grep -Po '\bstring2.*string5\b' file.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.