Пожалуйста, обратите внимание на код:
c=$(dd if=test1 skip=2 bs=1 count=1)
В разделе «Подстановка команд» в man bash
описано:
Bash выполняет расширение, выполняя команду ... с любым трейлингомновые строки удалены.
Из-за этого новая строка в результате выполнения команды dd
была удалена. Вы увидите это по тестовому коду ниже:
for (( i=1; i<=3; i++ )); do
c="$(dd if=test1 skip="$i" bs=1 count=1 2>/dev/null)"
echo "skip = $i"
echo -n "$c" | xxd
done
В общем случае bash
не подходит для явного обращения с символом перевода строки, поскольку bash иногда автоматически удаляет или добавляет его.
Если perl
является вашим вариантом, попробуйте следующее:
perl -0777 -ne '
$given = 3; # an example of the given offset
printf "character at offset %d = %s\n", $given, substr($_, $given, 1);
$pos = rindex(substr($_, 0, $given), "\n", $given);
if ($pos < 0) {
print "not found\n";
} else {
printf "newline found at offset %d\n", $given - $pos - 1;
}
' file
Если вы предпочитаете bash
, вот альтернатива в bash:
file="./file"
given=3 # an example of the given offset
str="$(xxd -ps "$file" | tr -d '\n')" # to the hexadecimal expression
for (( i=given; i>=0; i-- )); do
j=$(( i * 2 ))
c="${str:$j:2}" # substring offset j, length 2
if [[ $c = "0a" ]]; then # search for the substring "0a"
printf "newline found at offset %d\n" $(( given - i - 1 ))
exit
fi
done
echo "not found"
Концепция такая же, какверсия perl. Сначала он преобразует весь файл в шестнадцатеричное выражение и ищет подстроку «0a», начиная с заданной позиции в обратном направлении.
Надеюсь, это поможет.