当每行存在多个匹配项时,如何打印模式的行号和起始位置?

How to print the row number and starting location of a pattern when multiple matches per row are present?

我想使用 awk 来匹配一个大文件中出现的所有模式。对于每场比赛,我想打印行号和图案沿行的起始位置(某种 xy 坐标)。每行中出现几次该模式。 我发现 有点相关的问题。

到目前为止,我设法只对每一行中的第一个(最左边的)事件进行了处理。例如:

echo xyzABCdefghiABCdefghiABCdef | awk 'match([=10=], /ABC/) {print NR, RSTART } ' 

结果输出为:

1 4

但我期望的是这样的:

1 4
1 13
1 22

我尝试使用拆分而不是匹配。我设法识别所有事件,但 RSTART 丢失并打印为“0”。

echo xyzABCdefghiABCdefghiABCdef | awk ' { split([=13=],t, /ABC/,m) ; for (i=1; i in m; i++) print (NR, RSTART) } '

输出:

1 0
1 0
1 0

如有任何建议,我们将不胜感激。我不限于使用 awk,但 awk 解决方案将不胜感激。 此外,在我的例子中,要匹配的模式将是一个正则表达式 (/A.C/)。 谢谢

判断一个字符串的坐标用awk:

echo "xyzABCdefghiABCdefghiABCdef" \
  | awk -v s="ABC" 'BEGIN{ len=length(s) }
      {
        for(i=1; i<=length([=10=]); i++){
          if(substr([=10=], i, len)==s){
            print NR, i
          }
        }
      }'

输出:

1 4
1 13
1 22

作为一行:

echo xyzABCdefghiABCdefghiABCdef | awk -v s="ABC" 'BEGIN{ len=length(s) } { for(i=1; i<=length([=11=]); i++){ if(substr([=11=],i,len)==s) { print NR,i } } }'

来源:Find position of character with awk

这可能是您想要做的:

echo xyzABCdefghiABCdefghiABCdef | 
awk '{ begpos=1
       while (match(substr([=10=], begpos), /ABC/)) {
           print NR, begpos + RSTART - 1
           begpos += RLENGTH + RSTART - 1
       }
     }'

一个 awk 想法使用 split() 和一些 slicing-n-dicing of length() 结果:

ptn='ABC'

echo xyzABCdefghiABCdefghiABCdef | 
awk -v ptn="${ptn}" '
{ pos=-(length(ptn)-1)
  n=split([=10=],arr,ptn)
  for (i=1;i<n;i++) { 
      pos+=length(arr[i] ptn)
      print NR,pos
  }
}'

这会生成:

1 4
1 13
1 22

另一个使用 gnu awk 的选项可能是使用带有正则表达式的拆分。

使用split函数,第3个字段是fieldsep数组,第4个字段是seps数组,你们都可以用它们来计算位置。

echo xyzABCdefghiABCdefghiABCdef | 
awk ' { 
  n=split([=10=], a, /ABC/, seps); pos=1
  for(i=1; i<n; i++){
    pos += length(a[i])
    print NR, pos
    pos += length(seps[i])
  } 
}'

输出

1 4
1 13
1 22

使用您显示的示例,请尝试以下 awk 代码。

awk '
{
  prev=0
  while(match([=10=],/ABC/)){
    [=10=]=substr([=10=],RSTART+RLENGTH)
    print FNR,prev+RSTART
    prev+=RSTART+2
  }
}
'  Input_file

说明: 为以上添加详细说明。

awk '                              ##Starting awk program from here.
{
  prev=0                           ##Setting prev variable to 0 here.
  while(match([=11=],/ABC/)){          ##Using while loop to match ABC string and it runs till ABC match is ture in current line.
    [=11=]=substr([=11=],RSTART+RLENGTH)   ##Re-creating current line by assigning value of rest of line(which starts after match of ABC).
    print FNR,prev+RSTART          ##Printing line number along with prev+RSTART value here.
    prev+=RSTART+2                 ##Setting prev to prev+RSTART+2 here.
  }
}
'  Input_file                      ##Mentioning Input_file name here.