是否有可能在bash中从任意字节数偏移量开始读取文件?


22

我想找到一个8 GB日志(文本)中某处的日期。

我有点绕行一个完整的顺序读取,和第一可以做文件的二元分割(大小),或以某种方式浏览文件系统inodes(这是我知道的非常少约),开始从各个分割点读,直到我找到一个合适的距离偏移从哪里开始我的文本搜索以找到包含日期的行?

tail的最后一行的读取没有使用常规的顺序读取,因此我想知道bash中是否可以使用此功能,还是我需要使用Python或C / C ++ ...但是我对某个bash选项特别感兴趣..


Answers:


8
for (( block = 0; block < 16; block += 1 ))
do 
    echo $block; 
    dd if=INPUTFILE skip=$((block*512))MB bs=64 count=1 status=noxfer 2> /dev/null | \
        head -n 1
done

该..不创建临时分割文件,每次运行时跳过块* 512MB的数据,从该位置读取64字节,并将输出限制为该64字节的第一行。

您可能希望将64调整为所需的值。


@akira ..这看起来真的很好,但是我想再多看一点..(所以,直到明天.....
Peter.O 2011年

1
@akira ..'dd'太棒了。它与二进制拆分搜索效果很好...现在,我可以在不到1秒的时间内从排序的8G文件中提取正则表达式的行(通过其Date键)...看来我将实现3第二个人目标,用于提取两个键(包括两个键)之间的日期范围。.不包括输出时间,输出时间根据输出的量而有所不同。.我也将使用dd该时间...这是一个很棒的工具!:)
Peter.O 2011年

30

听起来像您想要的:

tail -c +1048576

或您要跳过的任何字节数。加号告诉尾巴从文件的开头而不是结尾开始测量。如果您使用的是GNU版本的tail,则可以这样写:

tail -c +1M

要在剪切后获得固定数量的字节,而不是文件的所有其余部分,只需将其通过head传递即可:

tail -c +1048576 | head -c 1024

Linux / bash的灵活性非常出色(我肯定花了太长时间切换到Linux)。我刚刚接受了akira的回答,但是直到我对这一点进行了更全面的评估之前,我一直将其保留下来。dd跳到一个特定的字节(与一样tail),但这是围绕未知行长度的痛苦编码,然后调用sed来剥离前导的部分行...看起来尾巴可以轻松地做到这一点(速度如此之快?)。 。我不了解头部如何关闭尾部的水龙头,但似乎是这样的:)一定是以下情况:如果头部停止接收,尾部停止发送(并停止进一步阅读)。必须去..明天再来。
Peter.O 2011年

@ fred.bear:tail/ head也不能盲目猜测行长。您必须跳到x的位置,然后才能在x的左边或右边寻找下一个\n。调用什么程序都没有关系。因此,在两种情况下,您都跳到x,然后使用head向右看下一行的结尾。
akira

tail|head提供能力,不必担心在所有有关dd的数= VAL。如果使用“ dd”,如果我没有获取足够的数据,那就是“游戏结束”。任意线路长度的灵活性很大。我已经为“ dd”编写了一个函数,该函数返回“下一个最近的”实线及其偏移量,但我希望避免长度问题。我现在已经测试了机头,它起初表现不错(偏移量为100MB),但是在偏移量= 8GB的情况下,一次访问需要2分钟的时间,因此速度显着降低(我可以awk在1分钟内完成)……所以很棒对于文件的..谢谢你让我知道了尾/头组合的:)
Peter.O

2

我会尝试类似的方法将日志分成512MiB块,以便更快地进行解析。

split <filename> -b 536870912

如果您要查找文件,则可以进行以下操作:

for file in x* ; do
  echo $file
  head -n 1 $file
done

使用该输出来确定您的日期要grep的文件。


谢谢,但是比顺序搜索要慢。在这里查看我的评论unix.stackexchange.com/questions/8121/…(而不是在这里重写相同的内容)
Peter.O 2011年

通过使用“分割”,您触摸每个单个字节一次。如果这样做,您也可以将整个8gb都grep起来。
akira

@sifusam ..我想进行二进制拆分搜索(不仅仅是拆分文件) en.wikipedia.org/wiki/Binary_search_algorithm ...因此,它是一个不同问题的好答案:) ..谢谢您的回答。 +1让您滚动....
Peter.O 2011年

0

这是我的脚本,我要寻找第一行,即第一个字段与我的号码匹配。这些行根据第一个字段进行排序。我使用dd检查128K块的第一行,然后跳转到该块并执行搜索。文件超过1M可以提高效率。

任何意见或纠正表示赞赏!

#!/bin/bash

search=$1;
f=$2;

bs=128;

max=$( echo $(du $f | cut -f1)" / $bs" | bc );
block=$max;
for i in $(seq 0 $max); do
 n=$(dd bs=${bs}K skip=$i if=$f 2> /dev/null| head -2 | tail -1 | cut -f1)
 if [ $n -gt $search ]; then
  block=`expr $i - 1` 
  break;
 fi
done; 
dd bs=${bs}K skip=$block if=$f 2> /dev/null| tail -n +2 | awk -v search="$search" '$1==search{print;exit 1;};$1>search{exit 1;};';

*编辑* ** grep更快, ack更好

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.