У меня есть такой пример input.txt
file:
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 -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
Для файла = input.txt и любого байтового смещения от 195 до 253 вывод должен быть:
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
Для файла = input.txt и байтового смещения = 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
Я могу читать символ за символом, запоминать последний символ новой строки и печатать с последнего символа новой строки до следующего. Это не будет работать с оболочками 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?