如何使用sed在两个模式之间提取线条并在循环中对其进行后期处理?

时间:2016-10-17 11:33:26

标签: awk sed

我想做这样的事情。说我有以下文字:

Start-pattern  
orange  
apple  
grape  
orange  
orange  
End-pattern  
#######  
bla bla bla  
########  
Start-pattern  
orange  
apple  
grape  
apple  
orange  
End-pattern  
#######
bla bla bla
########
Start-pattern  
orange  
orange  
orange  
End-pattern  
#######  
bla bla bla  
########

在这里,我想打印Start-patternEnd-pattern之间的橙子,苹果和葡萄的数量。

在上面的例子中,我们有3" orange",1" apple"和1"葡萄"在第一个开始模式和结束模式之间。 2"橙",2"苹果"和1"葡萄"在第二个SP和EP等等。

等待您的宝贵答案。

2 个答案:

答案 0 :(得分:3)

您可以试试awk

awk '$1 ~ /^Start-pattern$/{p=1;next} $1 ~ /^End-pattern$/{p=0; for (var in a) {print var,a[var];a[var]=""}; print "######"; next} p{a[$1]++}' file

更具可读性awk

$1 ~ /^Start-pattern$/ {
    p=1;
    next
}
$1 ~ /^End-pattern$/ {
    p=0;
    for (var in a) {
        print var,a[var];
        a[var]=""
    }
    print "######";
    next
} 
p {
    a[$1]++;
}

<强>解释

我们可以将此awk拆分为3个代码块。

  1. 检查Start-pattern模式,然后启用p=1
  2. 检查End-pattern模式,然后停用p=0。然后,打印a[]并显示相应的计数。
  3. 这将在关联数组中存储这两个模式之间每个项目的出现次数。

答案 1 :(得分:2)

这可能对你有用(GNU sed,echo,sort和uniq):

sed -nr '/Start/,/End/!b;/Start/h;//!H;/End/!b;x;s/^[^\n]*\n(.*)\n.*/echo "\1"|sort|uniq -c/e;s/\n//g;p' file

使用-n打开像大自然一样的seds grep。在保留空间(HS)中存储StartEnd之间的行,并在遇到End字符串时,从HS替换模式空间(PS)。删除开始和结束页眉/页脚并使用substitution命令的evaluate标志;将封闭的行回显为一个排序,然后使用uniq命令计算唯一的行。删除所有换行符并打印PS的内容。