【发布时间】:2019-05-15 09:24:41
【问题描述】:
我有这样一个例子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
另一个例子:
对于文件=input.txt 和字节偏移量=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
我可以逐个字符地阅读,记住最后一个换行符,并从最后一个换行符打印到下一个换行符。这不适用于 shell read,因为它省略了换行符。我想我可以使用 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 特定工具打印文件内“包含”字节偏移的整行?
【问题讨论】:
-
您的示例
input.txt不太清楚它是否是很长的行(包裹在几行以适应此页面布局)或者这些实际上是 3 个不同的行。在长线的情况下,“80”偏移量是有意义的,但不是“理想情况”的输出。 -
不,它们是几行,这就是我使用代码格式化的原因。我将尝试发布更多 lorem ipsum 和更多示例。
标签: bash shell gnu-coreutils