我有,我想通过从文件输出解析的问题,我想抓住在图案的两个之间的文本的第n次出现最好用awk或sed的
category
1
s
t
done
category
2
n
d
done
category
3
r
d
done
category
4
t
h
done
远的不说这个例子,我想抓住的类别和done之间文本的第三次出现,本质上是输出会
category
3
r
d
done
我有,我想通过从文件输出解析的问题,我想抓住在图案的两个之间的文本的第n次出现最好用awk或sed的
category
1
s
t
done
category
2
n
d
done
category
3
r
d
done
category
4
t
h
done
远的不说这个例子,我想抓住的类别和done之间文本的第三次出现,本质上是输出会
category
3
r
d
done
这可能会为你工作(GNU SED):
'sed -n '/category/{:a;N;/done/!ba;x;s/^/x/;/^x\{3\}$/{x;p;q};x}' file
通过关闭自动打印-n
选项。 收拾行之间category
和done
。 存储在保持空间的计数器,当它到达3打印集合中的模式空间和退出。
或者如果你喜欢AWK:
awk '/^category/,/^done/{if(++m==1)n++;if(n==3)print;if(/^done/)m=0}' file
试着这样做:
awk -v n=3 '/^category/{l++} (l==n){print}' file.txt
或者更神秘:
awk -v n=3 '/^category/{l++} l==n' file.txt
如果你的文件大:
awk -v n=3 '/^category/{l++} l>n{exit} l==n' file.txt
如果您的文件不包含任何空字符,这里的使用方式GNU sed
。 这将找到一个模式范围的第三次出现。 然而,你可以很容易地修改此得到任何你想要的发生。
sed -n '/^category/ { x; s/^/\x0/; /^\x0\{3\}$/ { x; :a; p; /done/q; n; ba }; x }' file.txt
结果:
category
3
r
d
done
说明:
关闭默认打印与-n
开关。 在一行的开始匹配单词“类”。 SWAP与保持空间模式空间和空字符追加到模式的开始。 在这个例子中,如果模式则包含了两个主要空字符,拉出来模式的holdspace。 现在创建一个循环,直到最后一个模式匹配打印模式空间的内容。 当这最后的模式被发现, sed
将退出。 如果它没有找到sed
将继续读取输入的下一行,并继续在其循环。
awk -v tgt=3 '
/^category$/ { fnd=1; rec="" }
fnd {
rec = rec $0 ORS
if (/^done$/) {
if (++cnt == tgt) {
printf "%s",rec
exit
}
fnd = 0
}
}
' file
随着GNU awk的,你可以设置的记录分隔符正则表达式:
<file awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3
输出:
category
3
r
d
done
RT
是匹配的记录分隔符。 需要注意的是相对于记录n
将由一个作为第一个记录是指第一什么先被关闭RS
。
按埃德的评论,当记录在它们之间有其它的数据,这将无法正常工作,例如:
category
1
s
t
done
category
2
n
d
done
foo
category
3
r
d
done
bar
category
4
t
h
done
要解决这个问题的方法之一是清理输入与第二(或第一)AWK:
<file awk '/^category$/,/^done$/' |
awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3
输出:
category
3
r
d
done
埃德在评论中指出,上述方法不搜索结局模式。 这样做的一种方式,这还没有被覆盖的其他的答案,是用getline
(注意,有一些注意事项使用awk函数getline):
<file awk '
/^category$/ {
v = $0
while(!/^done$/) {
if(!getline)
exit
v = v ORS $0
}
if(++nr == n)
print v
}' n=3
在一行:
<file awk '/^category$/ { v = $0; while(!/^done$/) { if(!getline) exit; v = v ORS $0 } if(++nr == n) print v }' n=3