如何将 "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 的酷孩子都在使用它的新功能。]
我有一个形式为 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 的酷孩子都在使用它的新功能。]