在文本文件中查找特定模式并将其从输出中排除?

在文本文件中查找特定模式并将其从输出中排除?

我有一个大约 25000 行的文件。看看我的示例输入和所需的输出

输入:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name sammy
* pwwn akslapsl
* pwwn dfgsjasl
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

期望的输出:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

我希望输出排除 pwwn 之前每一行中包含 * 的所有区域。在我的示例中,区域名称 sammy 在所有三个 pwwn 行中都有一个 *,因此我排除了区域名称 sammy 下的所有 * 行。

使用Solaris 5.10、Korn Shell。

答案1

Awk解决方案:

awk '/^zone /{ 
         if (f) print r;
         r = $0; f = 0; next 
     }
     { r = r ORS $0; if (/^[^*]* pwwn/) f = 1; }
     END{ if (f) print r }' file

输出:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

答案2

以下是我如何将其作为快速 Perl 管道来实现的:

perl -p00e 's/\nzone/\n\nzone/g' inputfile \
| perl -n00e '$t = $_; s/^\*.*?\n//mg; print $t if /pwwn/' \
| perl -p00e 's/\n\n/\n/'

第一行在每个记录之间添加一个空行。第二行迭代每个记录,检查pwwn删除该记录中以 * 开头的所有行后是否还有剩余行,如果有,则打印该记录。第三行删除分隔每条记录的空行。

答案3

$ awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input 
zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

awk脚本将记录分隔符 ( RS) 设置为输入文件的开头或换行符,后跟单词“zone”。然后它打印每条“记录”,其中至少包含一个换行符,后面没有*.

它必须打印单词“zone”,$0因为会自动从每个输入记录中awk删除“zone ”。RS

注意:因为RS它本身不仅仅是换行符,还$0包含每行输入末尾的换行符(这与上面提到的必须打印“zone”的原因密切相关)。这意味着输出的最后会有一个额外的空行。如果这是一个问题,解决它的最简单方法是使用sed.例如

awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input | sed '$d'

最后,如果pwwn是匹配条件的重要部分,则将脚本中的正则表达式匹配从 更改/\n[^*]//\n[^*] pwwn/。 (给定样本输入后,输出是相同的,但可能与更大的实际输入不同)

相关内容