AWK 按照模式打印

AWK 按照模式打印

文件:

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

期待:

string2 string3 string4 string5  
string2 string4 string5  
string2 string4 string1 string5

匹配模式=如何string1
打印匹配行但仅从string2string5awk

不幸的是,这不符合流程:

 awk '/string2/,/string5/' file 

我们假设在不同的地方有几条带有string2和的长线。string5

答案1

您可以使用 awkindexmatch函数,例如

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

前任。

$ 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

请注意,这假设在存在的string2每一行中都存在string5- 如果不是这种情况,您将需要检查的值index($0,"string2")并采取相应措施。

答案2

实际上,您要做的就是迭代每个字段,并在找到结果时使用变量“启用”打印。因此,您需要一个标志变量和 for 循环:

$ 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 

这里发生的情况是,整个代码块将针对每一行运行。在每一行上,我们从第一个字段迭代到最后一个字段。首先,我们将标志变量设置为 0,然后继续检查每个字段。如果字段包含所需的“string2”,则标志将设置为 1,如果它是“string6”(这是我们想要停止的那个)- 标志将设置为 0;最后,if 语句将检查是否设置了标志并打印当前字段并附加字段分隔符(由 FS 变量表示)。打印完所有内容后,我们还通过print ""命令插入换行符。

如果有不匹配的行,上述命令将打印空行。您可以通过添加搜索模式来缓解这种情况,这将仅在字符串中找到模式时才限制代码块的执行:

$ 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 

或者,我们可以使用额外的变量来获得相同的结果:

$ 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

答案3

首先,您只保留包含 和 的行string2,且string5这些行的顺序与特定顺序一致(第 1 行中的模式)。接下来,您要做的就是删除 和 之前string2以及 之后的所有内容string5(第 2 行和第 3 行),最后打印剩余的内容。

awk '/string2 .* string5/ {
    sub(/^.*string2/, "string2", $0);
    sub(/string5.*$/, "string5", $0);
    print $0;
}'

答案4

使用 grep:

grep -Po '\bstring2.*string5\b' file.txt

相关内容