如何在 gz 文件中不使用 grep 打印搜索关键字的前几行?

如何在 gz 文件中不使用 grep 打印搜索关键字的前几行?

grep如何在不使用.gz 文件的情况下打印搜索关键字之前的行?

ID:342N000390AAAAAAAA   07/14/15 10:26      (MV90    )
         * Register Data Imported
         * Warning - No Profile Data
     07/14/15 10:24  05/13/15 08:16       15    1   5956

我想搜索No Profile关键字并打印 ID 号,即 342N000390AAAAAAAA,并且必然“无配置文件”不会出现在第三行;它可以出现在任何行中。我的操作系统是HP-UX,所以很多命令不符合条件。

答案1

你可以使用awk

gzcat file.gz | awk '/No Profile Data/{printf "%s\n%s\n%s\n", b, a, $0} {b=a;a=$0}'
  • gzcat(或zcat在 Linux 上)将 gzip 压缩文件的内容打印到标准输出
  • awk然后搜索字符串"No Profile Data"并打印前两行

答案2

已编辑

新方法:删除换行符。

假设每个 gzip 压缩文件只有一个 ID,您可以尝试以下操作:

gunzip -c file.gz | sed -e ':a;N;$!ba;s/\n/ /g' -e '/^[[:space:]]/d' -e 's/^ID:\([[:alnum:]]*\).*Warning - No Profile Data.*/\1/' -e '/^ID:/d'
  • gunzip -c将文件解压到stdout
  • sed将所有行折叠成一行,然后删除所有不以 开头的行ID:,然后从匹配文件中提取 ID,然后删除不匹配文件的 ID: 行,以便它显示 ID 或不显示任何内容。

学分归因于https://stackoverflow.com/a/1252191/5148242https://unix.stackexchange.com/a/218094/124507@黑心

原来的

grep仍然是合适的选项,但为了练习,您可以使用sed查找结果和paste零件-B2

zcat nogrep.gz | paste - - - | sed -e '/^[[:space:]]/d' -e 's/^ID:\([[:alnum:]]*\).*Warning - No Profile Data/\1/' -e '/^ID:/d'
  • paste连接每组 3 条线
  • sed删除所有不以 开头的行ID:,然后从匹配文件中提取 ID,然后删除ID:不匹配文件的行,以便显示 ID 或不显示任何内容。

答案3

(希望)最终产品


find . -name \*.gz -type f -exec   gzcat {} +  |
sed -ne'/^ *ID:/h;/No Profile/!d;x' \
    -e's/^ *ID:\([^ ]*\).*/\1/p'

因此,这将递归地find根植于当前目录中的所有常规文件,其文件名与模式匹配*.gz,并调用zcat尽可能少的次数,以迭代地将单个流中的每个文件解压缩到sed标准输入。

sed将扫描其输入以查找以字符串开头的行*ID:。如果找到,它将h旧一个副本,然后寻找No Profile同时d删除所有不匹配的行。当发现时sed将交换到保留空间并尝试修剪^ *ID::行仅位于第一个和下一个发生之间的部分<空格>。如果成功,则sed p打印结果。

作为@DarkHeart 指出不过,您很可能必须在 HPUX 系统上将zcat命令名称更改为。gzcat


变化


这将是您在单个文件中搜索紧接在字符串匹配之前出现的行对所需的全部内容No Profile:

gzip -d <file.gz |
sed -e'1N;$!N;/\n.*No Profile/P;D'

这将一次只扫描输入三行。每行在\n模式空间中由一条 ewline 分隔。当每条N新行被拉入时,最旧的行被D删除。如果正则表达式\n.*No Profile在模式空间中曾经匹配过(当它是模式空间中最新的行时,以及当它是第二最新行时的下一个周期),打印最旧的行。所以你会得到之前发生的两行No Profile。如果您还想打印找到它的行...

gzip -d <file.gz |
sed -e'1N;$!N;/No Profile/P;D'

find


find . -name \*.gz -type f -exec zcat {} + |
sed -e'1N;$!N;/No Profile/P;D'

如果您愿意,您可以将.此处替换为某个目录的名称。您还可以添加\n.*No Profile位以避免打印匹配行。该命令将递归到..如果这不符合您的喜好:

find . \! -name . -prune -name \*.gz  \
          -type f -exec zcat {} +     |
sed -e'1N;$!N;/No Profile/P;D'

如果您专门寻找领先的ID字段,并且仅当可以在匹配之前找到两行No Profile你可以做:

find . -name \*.gz -type f -exec zcat {} + |
sed -ne'/^ID/!D;/\n/!N;N' \
     -e's/ .*\n.*\n.*No Profile.*//p;D'

...这只会打印前导ID字段,因为它可能出现在任何/所有*.gz文件find调用zcat打印并且仅当ID肯定出现在 a 之前两行No Profile匹配。

相关内容