Python:获取字符串索引的行列号?
假设我有一个正在操作的文本文件。内容大概是这样的(希望这不是太难懂):
data_raw = open('my_data_file.dat').read()
matches = re.findall(my_regex, data_raw, re.MULTILINE)
for match in matches:
try:
parse(data_raw, from_=match.start(), to=match.end())
except Exception:
print("Error parsing data starting on line {}".format(what_do_i_put_here))
raise
注意在异常处理器里有一个叫 what_do_i_put_here
的变量。我的问题是:我该怎么给这个变量赋值,这样我的脚本就能打印出我想处理的“坏区域”开始的行号?我不介意重新读取文件,只是不知道该怎么做……
3 个回答
0
列的索引是从0开始的,所以在你代码的最后,需要从len(sp[-1])中减去1,才能得到正确的列值。此外,如果字符串的长度为0,或者字符串太短,无法满足索引的要求,我建议返回None(而不是“1.1”,因为这也是错误的,应该是“1.0”)。
总的来说,这是一个很棒且优雅的解决方案,Tim。
def index_to_coordinates(txt:str, index:int) -> str:
"""Returns 'line.column' of index in 'txt'."""
if not txt or len(txt)-1 < index:
return None
sp = txt[:index+1].splitlines(keepends=True)
return (f"{len(sp)}.{len(sp[-1])-1}")
1
我写了这个代码。虽然还没测试过,而且效率也不高,但它确实能让我的错误信息更清楚一些:
def coords_of_str_index(string, index):
"""Get (line_number, col) of `index` in `string`."""
lines = string.splitlines(True)
curr_pos = 0
for linenum, line in enumerate(lines):
if curr_pos + len(line) > index:
return linenum + 1, index-curr_pos
curr_pos += len(line)
我甚至还没测试过列号是否大致正确。我没有遵循YAGNI原则。
3
这里有一个更简洁的写法,我觉得比你自己的答案更容易理解:
def index_to_coordinates(s, index):
"""Returns (line_number, col) of `index` in `s`."""
if not len(s):
return 1, 1
sp = s[:index+1].splitlines(keepends=True)
return len(sp), len(sp[-1])
它的工作原理基本和你的答案一样,但通过使用字符串切片的 splitlines()
方法,实际上可以自动计算出你需要的所有信息,而不需要额外的处理。
使用 keepends=True
是必要的,这样才能正确计算行末字符的数量。
唯一需要注意的额外问题是空字符串的情况,这个可以通过一个简单的保护措施来处理。
我在 Python 3.8 中测试过,但大概从 3.4 版本开始就能正常工作(在一些旧版本中,len()
计算的是代码单元而不是代码点,我猜如果字符串中包含 BMP 以外的字符,可能会出问题)。