已获得一个日志文件,其中包含文件名的结构化列表,第一个文件由描述符标识File:
,其余文件位于单独的行上,+
开头有一个字符。
我想要一个循环,一旦File:
检测到,就使用匹配的模式打印文件名。然后它将继续拾取+
开头的文件名。当到达空行或遇到另一个字段名称时,文件读取停止(例如Package:
)
cat /home/flora/logs/27043-T13:09:44.893003954.log
%rec: dyna
Ptrn: Gnu
File: /home/flora/dynamic.sh
+ /home/flora/comint.sh
+ /home/flora/linge/engine.sh
+ /home/flora/Opstk/playa.sh
+ /home/flora/bin/edv.sh
+ /home/flora/Opstk/bin/ling.rc
+ /home/flora/parade.rc
System: 64-Bit
从一个简单的开始read
,以免使用变量来存储整个文件列表时导致内存不足问题。
while IFS= read -rd '' fl; do
grep --color -ni -C 8 -e "$ptrn" -- "$fl"
done < "$logfl"
ptrn
定义对每个文件调用的搜索模式。
答案1
在对该问题的评论中recutils
,您提到您已将这些数据转换为 GNU工具集可读的格式。
让我们使用这些工具来提取路径名并调用grep
:
recsel -P File -- "$logfl" | xargs -I {} grep -e "$ptrn" -- {}
File
这将选择并打印与名为 的文件中的字段关联的值$logfl
。对于命令生成的每一行recsel
,xargs
调用grep
以提取与 中的基本正则表达式匹配的行$ptrn
。
请注意,问题文件中的内容是单身的值,包含嵌入的换行符。
如果您有一个记录文件,其中包含多个File
带有单独值的字段,您可以使用
recsel -C -P File -- "$logfl" | xargs -I {} grep -e "$ptrn" -- {}
答案2
使用进程替换并仅传递带有文件名的行进行循环(而不是整个文件)
while IFS= read -r fl; do
grep --color -ni -C 8 -e "$ptrn" -- "$fl"
done < <(grep -o '/.*' "$logfl")
或处理整个文件,但逐行跳过直到关键字File:
出现,然后通过字符串操作逐行处理/${fl#*/}
直到关键字+
消失,然后停止读取
# some control flags
begin=
exit=continue
while IFS= read -r fl; do
case ${fl%[[:blank:]]*} in
*File:*)
begin=start
;;
*+*)
exit=break
;;
*)
$exit
;;
esac
[ "$begin" ] && \
grep --color -ni -C 8 -e "$ptrn" -- "/${fl#*/}"
done < "$logfl"