如何将 "file:linenumber:offset" 转换为 "file#byteoffset"

How to convert "file:linenumber:offset" to "file#byteoffset"

我有一个形式为 file:linenumber:offset 的符号位置,例如:

/a/b/c/transform_throttle.go:96:6

所以它指的是第 96 行,第 6 列。如何将其转换为如下格式 file#byteoffset,仅显示从该(示例)文件开始的字节偏移量 1501?

/a/b/c/transform_throttle.go:#1501

我同意@cdarke 的观点,bash 不是这项工作的最佳工具。也就是说:

#!/bin/bash
(( $# != 1 )) && {
    echo "usage: [=10=] /a/b/c/transform_throttle.go:96:6"
    exit
}

target_file=${1%%:*}
tmp=${1#*:}
target_line=${tmp%:*}
target_offset=${tmp#*:}

while IFS= read -r line; do
    (( linenum++ ))
    if (( linenum == target_line )); then
        (( byteoffset += target_offset ))
        echo $target_file:#$byteoffset
        exit
    else
        (( byteoffset += (${#line} + 1) ))  # +1 for newline
    fi
done < $target_file

这是一个 python 3 的解决方案:

import sys

if len(sys.argv) < 2:
    print("Usage:", sys.argv[0], "input-file output-file", file=sys.stderr)
    sys.exit(1)

inputfile = sys.argv[1]
outputfile = sys.argv[2]

with open(inputfile) as inf, open(outputfile, 'w') as outf:
    while True:
        pos = inf.tell()   # Get the file position before the read
        line = inf.readline()
        if not line:
            break
        print("%s:%d" % (line.split(':')[0], pos), file=outf)

假设 python 脚本被调用 gash.py,运行 它是这样的:

python gash.py in.txt out.txt

如果您需要 python 2(python -V 来查找您的版本),则需要更改 print 语句。

我应该补充一点,使用 readline() 不是从 python 读取文件的正常方法 - 通常我们使用 for 循环遍历文件。但是我们需要当前文件位置,而这在使用迭代时是不允许的,所以我们必须做很长的路。

我有时所做的是维护一个辅助索引,将输入文件行映射到字节偏移量。这是一个 stripped-down 示例:

function mkindex {
    grep --byte-offset ^  | sed 's/:.*//' > 
}

# usage: findoffset file line char

file=
line=
char=
ix=.$file.ix

if test ! -f $ix -o $file -nt $ix
then    mkindex $file $ix
fi

o1=`sed -n ${line}p $ix`
if test -z "$o1"; then echo "[=10=]: $file: nonexistent line $line" >&2; exit 1; fi
o2=`expr $o1 + $char - 1`

echo $file:$o2

调用为

script /a/b/c/transform_throttle.go 96 6

这应该会给你想要的输出。

它有一个低效之处:它在其索引文件中执行昂贵的线性搜索以查找所需的行。最好使用二分查找。 (我在 sh 中编写了二进制搜索,虽然它有点乱。command-line binary-search 实用程序会很好,但我不知道标准的实用程序。我使用 https://www.eskimo.com/~scs/src/#bsearch .)

它抱怨不存在的行,但它对行内不存在的列没有做任何聪明的事情。它也缺少 error-checking 丢失的文件。如果您不希望它用永远不会删除的索引文件乱丢您的目录,您就不会想要使用这种解决方案。

[哦,我想我应该为我的 old-school backtic 和 expr 用法道歉。我想所有 bash 的酷孩子都在使用它的新功能。]