相同模式之间的 awk 或 sed 行(包括第一个匹配项)

相同模式之间的 awk 或 sed 行(包括第一个匹配项)

这是正文:

* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included

该文本的输出应该是这样的:

* Tue This is the first line

– info 1

– info 2

– info 3

注意:我尝试过 awk 和 sed 但未能得出我的输出。问题是 START 和 END 是相同的“*”(星号),并且第一个应该包含在输出中。

答案1

我希望我正确理解这一点。该脚本将从第二行开始*直到缓冲区末尾删除所有内容,从而从示例中生成所需的输出:

sed -n 'H;1h;$x;$s/\(\*[^*]*\)\n\*.*$/\1/p'

说明 将所有行 ( H) 添加到保持缓冲区。对于最后一行交换保持和模式缓冲区 ( $x),因此您将整个文件作为一个模式。在此模式中,要保留的部分设置\(\)并保留 ( \1),而换行符中的所有内容都*将被删除。

这符合您的描述,但如果它不符合所有可能的示例,您可以修改脚本。

答案2

perl -lne 'if ( m?^\*? ... m?^\*? ) { print if !// || !$a++ }'

sed -e '
   /^\*/!d
   :loop
       $q; N
   /\n\*/!bloop
   s/\(.*\)\n.*/\1/;q
'

sed -e '
   /^\*/!d
   :loop
      n
   //!bloop
   Q
'

答案3

将示例文本保存到变量:

$ SAMPLE=$(cat <<EOF
* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included
* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included
EOF
)

用于awk处理您的$SAMPLE

$ awk '{if($1~"\*"){if(p==1){p=0;next}else{p=1}}if(p==1){print $0}}' <<<"$SAMPLE"
* Tue This is the first line

– info 1

– info 2

– info 3

* Tue This is the first line

– info 1

– info 2

– info 3

编辑

正如评论中所建议的,有一个令人惊讶的优雅awk解决方案:

$ awk '/^\*/{p=!p};p' <<<"$SAMPLE"
* Tue This is the first line

– info 1

– info 2

– info 3

* Tue This is the first line

– info 1

– info 2

– info 3

怎么运行的:

  • /^\*/{p=!p};- 这会将 的值交替p1和。当第一次找到正则表达式时0,它将变为。第二次找到时,它将变为,依此类推。1/^\*/p0

  • p- 这相当于p{print}.由于print是 中的默认操作,因此当前提条件计算为该值时(在本例中当变为时awk),它将始终打印。truep1

相关内容