首页 > 解决方案 > 如何打印文件中包含指定字节偏移的整行?

问题描述

我有这样一个示例input.txt文件:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.

现在我可以轻松地 grep 一个单词并获得它的字节偏移量:

$ grep -ob incididunt /dev/null input.txt 
input.txt:80:incididunt

可悲的是,有关行内容的信息和有关搜索词的信息会丢失。我只知道文件名和80字节偏移量。我想在文件中打印包含该字节偏移量的整行。

所以理想情况下,得到一个script.sh带有两个参数,一个文件名和一个字节偏移量,输出搜索到的行:

$ ./script.sh input.txt 80
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut

另一个例子:

对于 file=input.txt 和 byte offset=130,输出应该是:

enim ad minim veniam, quis nostrud exercitation ullamco laboris

对于 file=input.txt 和 195 到 253 之间的任何字节偏移,输出应为:

nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor

对于 file=input.txt 和 byte offset=400,输出应该是:

sunt in culpa qui officia deserunt mollit anim id est laborum.

我努力了:

我可以使用 gnu sed 从字节偏移量打印到行尾,但是错过了eiusmod tempor部分。我想不出任何想法如何在文件中“返回”,从换行符中获取部分直到那个字节偏移。

$ sed -z 's/.\{80\}\([^\n]*\).*/\1\n/' input.txt 
incididunt ut labore et dolore magna aliqua. Ut

我可以逐个字符地阅读,记住最后一个换行符,并从最后一个换行符打印到下一个换行符。这不适用于 shells read,因为它省略了换行符。我想我可以让它与 using 一起工作dd,但肯定有一个更简单的解决方案。

set -- inpux.txt 80
exec 10<"$1"
pos=0
lastnewlinepos=0
for ((i=0;i<"$2";++i)); do
        IFS= read -r -u 10 -N 1 c
        pos=$((pos+1))
        # this will not work..., read omits newlines
        if [ "$c" = $'\n' ]; then
                lastnewlinepost="$pos"
        fi
done
# as I know the last newline before the offset, it's ok to use this now
sed -z 's/.\{'"$lastnewlinepos"'\}\([^\n]*\).*/\1\n/' "$1"

如何使用 bash 和 *nix 特定工具打印文件内“包含”字节偏移的整行?

标签: bashshellgnu-coreutils

解决方案


使用 GNU awk,将到目前为止读取的字节数保存在一个变量中,当它达到您的字节偏移量时,打印当前行并退出。例如:

$ awk -b '{ nb += length + 1 } nb >= 80 { print; exit }' file
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut

关键字length是 的简写length($0),它以字节为单位返回当前行的长度(感谢-b)。我们需要将 1 添加到它,因为 awk 会去除行终止符。


推荐阅读