从结束到开始 Awking 文件的更快方法?
Faster way of Awking a file from End to Beginning?
我想从文件底部开始获取结果,然后一直到开头。我尝试使用 tac
并将其通过管道传输到我的 awk
命令中,但它非常慢(2GB 文件需要 15 秒)。与正常搜索相比(同一文件搜索 3 秒)。我还将 awk
命令传送到 tail -n +1 | head -n 50
以在 50 个结果后停止。
有没有更快的方法 tac
一个文件?或者至少从下往上开始搜索?
大局是创建一个 python 脚本,该脚本接受参数(开始日期、结束日期、搜索词)并使用这些参数来搜索按日期组织的日志文件。一次返回 50 个结果。
我需要从头到尾阅读,以防用户想要按降序(从最新日期到最旧日期)搜索。
用于升序结果的示例命令(“最旧到最新”):
(我正在使用查找,因为是用户指定的参数,它可能会引用所有文件 (*.txt))
- 开始日期:2018-03-04T03:45
- 结束日期:2018-03-05T16:24
- 搜索词:马铃薯
find '/home/logs/' -type f -name 'log_file.txt' -exec cat {} \+ 2>&1| LANC=C fgrep 'Potato' | LC_ALL=C IGNORECASE=1 awk -v start="2018-03-04T03:45:00" -v stop="2018-03-05T16:24:59" 'BEGIN{IGNORECASE=1;} {line=[=15=]; xz=" "; for(i=4;i<=NF;i++){xz=xz" "$i};} (>=start&&<=stop) && (tolower(xz) ~ /Potato/) {print line}' | tail -n +1 | head -n 50
tail -n +1 | head -n 50
是 return 前 50 场比赛。
此命令大约需要 3-4 秒才能找到结果,但是如果我在 tac 中进行 sub,则需要将近 20 秒。
好吧,如果你有记忆,散列记录并在 END
部分向后处理:
$ for i in {a..e} ; do echo $i ; done |
awk '{ a[NR]=[=10=] } # hash to a, NR as key
END { # in the end
for(i=NR;i>=1;i--) # process a in descending order
c++ # process
print c
}'
5
更新:我在上面测试了一个 1 GB 的文件(36 M 记录)。它在 1 分钟内进行了散列和计数,并占用了大约 4.5 GB 的内存。
一切都在一定程度上取决于您拥有的 awk
代码,但我想到的一些解决方案是:
如果你打印每一行:
tac <file> | awk '(NR > 50){exit}{do-your-stuff}'
如果只打印几行 awk
tac <file> | awk '(c > 50){exit}
{ do-part-of stuff;
print foobar; c++;
do-remaining part}'
两种解决方案都在前 50 行打印后终止 awk
。这样您就不必处理整个 2GB 的文件。 50 行打印后的终止模仿 tail -n +1 | head -n 50
打开文件的速度大大加快,并在文件结束前搜索到一定数量。 Perl 在这里很方便:
perl -Mautodie -se '
$size = -s $file;
$blocksize = 64000;
open $fh, "<", $file;
seek $fh, $size - $blocksize, 0;
read $fh, $data, $blocksize;
@lines = split "\n", $data;
# last 50 lines
print join "\n", reverse @lines[-51..-1];
' -- -file="filename"
我们可以在其中加入一个循环,这样在它读取最后一个块之后,它可以寻找到减去 2 个块的末尾并读取一个块,等等。
但是如果你想从下到上处理整个巨大的文件,你将不得不期待它需要时间。
我想从文件底部开始获取结果,然后一直到开头。我尝试使用 tac
并将其通过管道传输到我的 awk
命令中,但它非常慢(2GB 文件需要 15 秒)。与正常搜索相比(同一文件搜索 3 秒)。我还将 awk
命令传送到 tail -n +1 | head -n 50
以在 50 个结果后停止。
有没有更快的方法 tac
一个文件?或者至少从下往上开始搜索?
大局是创建一个 python 脚本,该脚本接受参数(开始日期、结束日期、搜索词)并使用这些参数来搜索按日期组织的日志文件。一次返回 50 个结果。
我需要从头到尾阅读,以防用户想要按降序(从最新日期到最旧日期)搜索。
用于升序结果的示例命令(“最旧到最新”): (我正在使用查找,因为是用户指定的参数,它可能会引用所有文件 (*.txt))
- 开始日期:2018-03-04T03:45
- 结束日期:2018-03-05T16:24
- 搜索词:马铃薯
find '/home/logs/' -type f -name 'log_file.txt' -exec cat {} \+ 2>&1| LANC=C fgrep 'Potato' | LC_ALL=C IGNORECASE=1 awk -v start="2018-03-04T03:45:00" -v stop="2018-03-05T16:24:59" 'BEGIN{IGNORECASE=1;} {line=[=15=]; xz=" "; for(i=4;i<=NF;i++){xz=xz" "$i};} (>=start&&<=stop) && (tolower(xz) ~ /Potato/) {print line}' | tail -n +1 | head -n 50
tail -n +1 | head -n 50
是 return 前 50 场比赛。
此命令大约需要 3-4 秒才能找到结果,但是如果我在 tac 中进行 sub,则需要将近 20 秒。
好吧,如果你有记忆,散列记录并在 END
部分向后处理:
$ for i in {a..e} ; do echo $i ; done |
awk '{ a[NR]=[=10=] } # hash to a, NR as key
END { # in the end
for(i=NR;i>=1;i--) # process a in descending order
c++ # process
print c
}'
5
更新:我在上面测试了一个 1 GB 的文件(36 M 记录)。它在 1 分钟内进行了散列和计数,并占用了大约 4.5 GB 的内存。
一切都在一定程度上取决于您拥有的 awk
代码,但我想到的一些解决方案是:
如果你打印每一行:
tac <file> | awk '(NR > 50){exit}{do-your-stuff}'
如果只打印几行
awk
tac <file> | awk '(c > 50){exit} { do-part-of stuff; print foobar; c++; do-remaining part}'
两种解决方案都在前 50 行打印后终止 awk
。这样您就不必处理整个 2GB 的文件。 50 行打印后的终止模仿 tail -n +1 | head -n 50
打开文件的速度大大加快,并在文件结束前搜索到一定数量。 Perl 在这里很方便:
perl -Mautodie -se '
$size = -s $file;
$blocksize = 64000;
open $fh, "<", $file;
seek $fh, $size - $blocksize, 0;
read $fh, $data, $blocksize;
@lines = split "\n", $data;
# last 50 lines
print join "\n", reverse @lines[-51..-1];
' -- -file="filename"
我们可以在其中加入一个循环,这样在它读取最后一个块之后,它可以寻找到减去 2 个块的末尾并读取一个块,等等。
但是如果你想从下到上处理整个巨大的文件,你将不得不期待它需要时间。