【发布时间】:2018-05-26 01:20:14
【问题描述】:
我有现有的日志文件,其中包括以下类型的行:
2018-05-14T10:10:22.769029+03:00 timom usbmonitor: [INFORMATION 6] [FILE: UsbChecker.cpp:51][FUNC: vendorCheck][MSG: USB vendors changed: "0403 14e1 05e3 05e3 03f0 0403 0bda 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b" ]
从这些文件中,我想 grep 上面的行,以便从开头获取时间戳和引号内的文本,以便我有一个漂亮而紧凑的输出:
2018-05-14T10:10:22.769029+03:00 0403 14e1 05e3 05e3 03f0 0403 0bda 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b
有没有办法用单线做到这一点?
我正在寻找一种无需遍历 grepped 行即可有效获得所需输出的方法。我有数千个日志文件,每个可能有数百个匹配项,因此 grep/sed/whatever 需要高效。
到目前为止,我已经这样做了:
#!/bin/bash
INPUTDIR=
OUTPUTDIR=
while getopts ":h:d:o:" OPTION; do
case $OPTION in
h)
usage
exit 1
;;
d)
INPUTDIR=$OPTARG
;;
o)
OUTPUTDIR=$OPTARG
;;
?)
usage
exit 1
;;
esac
done
if [ -z $INPUTDIR ] || [ -z $OUTPUTDIR ]; then
echo "BAD ARGUMENTS: both directories aren't given" >&2
usage
exit 1
fi
OUTPUTFILE="$(date +%Y%m%d%H%M%S)-usb-analysis-summary"
for i in $( ls $INPUTDIR ); do
# Interesting files are of format <number>_<number>
if [ $(echo "$i" | grep -Ev "^[0-9]+_[0-9]+$") ] ; then
echo "Skipping $i"
continue
fi
grep vendorCheck $INPUTDIR/$i | while read -r l ; do
# We do know timestamp is 32 characters long. GEFN
echo "$l" | sed -r "s|^(.{32}).*changed: \"(.*)\".*|\1 \2|" >>$OUTPUTFILE
done
done
但这不是最优的,因为现在我正在循环文件,然后从每个文件中循环 grep 匹配项。
我试过了
grep "vendorCheck" $INPUTDIR/$i | sed -r "s|^(.{32}).*changed: \"(.*)\".*|\1 \2|"
但这会删除换行符。
然后,如果我将多个模式放在一个 grep 中,我也会遇到格式化问题;我需要将引号内的时间戳和文本放在一行中,并将下一个类似的匹配项放在下一行。
【问题讨论】:
-
你可以在这里查看,一次Grep两个模式stackoverflow.com/a/30684014/7020538
-
@AbhijithSAchal 谢谢,但这并不能回答我的问题。 grep "string1|string2" 会给我所有匹配字符串的行。我已经用 grep "vendorCheck" 对所需的行进行了 grep,并且从这些行中的每一行我想得到两个确切的模式并转储其他所有内容。