Linux 如何查找文件中特定行的字节位置
从命令行查找文件中特定行的字节位置的最快方法是什么 e、 g 我正在为一个大小为几GB的CSV编写一个解析器,如果解析器停止,我希望能够从最后一个位置恢复。解析器是用Python编写的,但即使是在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命令来有效地执行此操作 编辑:很抱歉造成混淆,但我正在寻找一个非
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 '!@##$@#%%^%&*%^&*(^)((**%%^@#' <<<'!@##$@#%%^%&*%^&*(^)((**%%^@#'
!@##$@#%%^%&*%^&*(^)((**%%^@#