sed在2个模式和选择n出现之间打印文本

时间:2017-09-21 15:42:25

标签: design-patterns sed

我已经过了一小时在网上搜索,但我找不到解决问题的方法,看起来很简单......

我有一个多模式匹配的文件

----PATERN1----
textaa1
textbb1
textcc1
.......
----PATERN2----
----PATERN1----
textaa2
textbb2
textcc2
.......
----PATERN2----
----PATERN1----
textaa2
textbb2
textcc2
.......
----PATERN2----
etc...

这是我用命令

获得的输出
sed -n '/PATERN1/,/PATERN2/p' file

但问题是我怎样才能选择第n次出现? (1 - 2- 3等......然后我可以用变量替换) 提前致谢

3 个答案:

答案 0 :(得分:1)

这可能适合你(GNU sed):

sed -nr '/PATTERN1/H;//,/PATTERN2/G;/\n(\n[^\n]+){2}$/P' file

将保留空间用作计数器,并仅打印与所需数字匹配的行,即上面的数字为2。

N.B。假设PATTERN1PATTERN2在整个文件中匹配。

答案 1 :(得分:1)

这很容易,但你试图使用错误的工具。 sed适用于s/old/new/全部以及其他任何内容,例如您正在使用awk代替。

$ awk -v n=2 '
    /PATERN1/ {f=1; rec=""}
    f {
        rec = rec $0 ORS
        if (/PATERN2/) {
            if (++c == n) {
                printf "%s", rec
            }
            f=0
        }
    }' file
----PATERN1----
textaa2
textbb2
textcc2
.......
----PATERN2----

请注意,上述内容适用于任何UNIX系统中任何shell中的任何awk,如果你想选择不同的记录号打印你,上面你不需要多次测试以太PATERN只需在命令行中更改n的值,如果您想按照数字打印多个记录,那么这是一个微不足道的明显调整:

$ awk -v n=2 -v m=7 '
    /PATERN1/ {f=1; rec=""}
    f {
        rec = rec $0 ORS
        if (/PATERN2/) {
            if ( (++c == n) || (c == m) ) {
                printf "%s", rec
            }
            f=0
        }
    }' file

如果你想测试特定的文字" foo"在块内,而不是(或除了)测试一个数字,它也是微不足道的,显而易见的:

$ awk '
    /PATERN1/ {f=1; rec=""}
    f {
        rec = rec $0 ORS
        if (/PATERN2/) {
            if (rec ~ /foo/) {
                printf "%s", rec
            }
            f=0
        }
    }' file

如果你想在每个区块内打印特定的线条或删除换行符或其他任何内容,它也是微不足道的,因为上面使用的是正确的工具。

答案 2 :(得分:0)

你能不能尝试跟踪awk,你也可以提供一些事件。

 awk -v occur=2 -v regex1="PATERN1" -v regex2="PATERN2" '(occur * 2)==count{print val;val=""} $0 ~ regex1{count++} $0 ~ regex2{count++} {val=val?val ORS $0:$0}'  Input_file

此处也添加非单线形式的解决方案。

awk -v occur=2 -v regex1="PATERN1" -v regex2="PATERN2" '
(occur * 2)==count{
  print val;
  val=""
}
$0 ~ regex1{
  count++
}
$0 ~ regex2{
  count++
}
{
  val=val?val ORS $0:$0
}
'   Input_file

解决方案第二:如果您的Input_file已损坏且每个块中的PATTERN2后面没有PATTERN1序列,那么以下内容也可以帮助您。

awk -v occur=2 -v regex1="PATERN1" -v regex2="PATERN2" '
$0 ~ regex1 && flag{
  val=""
}
(occur * 2)==count{
  print val
  val=""
  count=""
}
{
  val=val?val ORS $0:$0
}
$0 ~ regex1{
  count++
  flag=1
}
$0 ~ regex2 && count{
  count++
  flag=""
}
END{
  if((occur * 2)==count){
    print val
}
}
'  Input_file

PS:我在考虑从Pattern1到Pattern2的出现意味着1次。

第二个解决方案的PS:如果您不想在用户提及的出现次数(对于匹配的字符串/正则表达式/模式)中添加count="",则您不想打印任何内容$0 ~ regex1 && flag{也阻止了。