Linux 如何查找文件中特定行的字节位置

Linux 如何查找文件中特定行的字节位置,linux,bash,command-line,Linux,Bash,Command Line,从命令行查找文件中特定行的字节位置的最快方法是什么 e、 g 我正在为一个大小为几GB的CSV编写一个解析器,如果解析器停止,我希望能够从最后一个位置恢复。解析器是用Python编写的,但即使是在file.readlines()上迭代也需要很长时间,因为文件中有数百万行。我只想执行file.seek(int(command.getoutput(“linepos myfile.txt%I”%lastrow)),但我找不到一个shell命令来有效地执行此操作 编辑:很抱歉造成混淆,但我正在寻找一个非

从命令行查找文件中特定行的字节位置的最快方法是什么

e、 g

我正在为一个大小为几GB的CSV编写一个解析器,如果解析器停止,我希望能够从最后一个位置恢复。解析器是用Python编写的,但即使是在
file.readlines()
上迭代也需要很长时间,因为文件中有数百万行。我只想执行
file.seek(int(command.getoutput(“linepos myfile.txt%I”%lastrow))
,但我找不到一个shell命令来有效地执行此操作


编辑:很抱歉造成混淆,但我正在寻找一个非Python的解决方案。我已经知道如何在Python中实现这一点。

在文件对象上迭代会产生完整的行结尾。您应该能够将
len
s添加到计数器对象以获得位置。您需要基于字符编码(字符字节大小)进行乘法


@chepner对我的另一个答案的评论:

position = 0  # or wherever you left off last time
try:
    with open('myfile.txt') as file:
        file.seek(position)  # zero in base case
        for line in file:
            position = file.tell() # current seek position in file
            # process the line
except:
    print 'exception occurred at position {}'.format(position)
    raise

如果你的模式很简单,这就很简单了

$ echo -e '#!/bin/bash\necho abracadabra' >/tmp/script
$ pattern=bash
$ sed -rn "0,/$pattern/ {s/^(.*)$pattern.*$/\1/p ;t exit; p; :exit }" /tmp/script \
    | wc -c 
8
如您所见,这将输出模式中第一个字符的位置,假设文件中的第一个字符的编号为1

注1:
sed
习惯于在它解析的最后一个字符串中添加一个尾随的换行符,因此,当我们获取
模式
前面的一部分行时,输出中的字节数应该是7(计算它们)→
#!/bin/
),但是
wc-c
实际计算的是什么

$ sed -rn "0,/$pattern/ {s/^(.*)$pattern.*$/\1/p ;t exit; p; :exit }" /tmp/script \
   | hexdump -C
00000000  23 21 2f 62 69 6e 2f 0a                           |#!/bin/.|
00000008
例如,如果您正在寻找EOF,这可能是潜在的问题源。我想不出更合适的例子了,我只想指出这一点

注2:若模式包含特殊字符,sed将失败。如果你能举例说明你在寻找什么,我可以逃避

注意3:这假设
模式
是唯一的。如果在第二个或第三个
模式实例上停止读取文件,这将不起作用


更新。 我找到了一个更简单的方法

$ grep -bo bash <<< '#!/bin/bash'
7:bash
我建议使用grep,因为如果指定
-F
键,它会将模式视为一个简单的字符串

$ grep -F '!@##$@#%%^%&*%^&*(^)((**%%^@#' <<<'!@##$@#%%^%&*%^&*(^)((**%%^@#' 
!@##$@#%%^%&*%^&*(^)((**%%^@#

$grep-F'!@##$@#%^%和*%^&*(^)((***%^@#“更简单地说,
position=file.tell()
将保存当前位置。同样正确的是,文本不是每个输出位置的一个字符(正式的代码点,请看一下全部内容).老实说,这应该是一个新的答案。它比我的答案要好得多,而且从根本上说different@vonbrand,我确实说过基于字符字节大小的乘法,就像python一样,我更喜欢请求许可而不是原谅:)
$ grep -bo bash <<< '#!/bin/bash'
7:bash
-b, --byte-offset
    Print the 0-based byte offset within the input file before  each  line  of
    output. If -o (--only-matching)  is specified, print the offset of the
    matching part itself.
$ grep -F '!@##$@#%%^%&*%^&*(^)((**%%^@#' <<<'!@##$@#%%^%&*%^&*(^)((**%%^@#' 
!@##$@#%%^%&*%^&*(^)((**%%^@#