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/5148242和https://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
匹配。