当每行存在多个匹配项时,如何打印模式的行号和起始位置?
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 } } }'
这可能是您想要做的:
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.
我想使用 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 } } }'
这可能是您想要做的:
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.