как определить перевод строки в bash? - PullRequest
0 голосов
/ 30 октября 2019

Файл:

a
b

команда запуска

dd if=file count=1 skip=0 bs=1 # show a
dd if=file count=1 skip=1 bs=1 # show "newline"
dd if=file count=1 skip=2 bs=1 # show b

Я хочу найти смещение первой «новой строки» перед заданным смещением с помощью оператора «if» вскрипт bash (который является фиктивным способом):

para1=$1
while(1)
do
    c=$(dd if=file count=1 bs=1 skip=$para1)
    if [ $c -eq "\n" ]   # How to write this line?
    then
        break
    fi
    para1=`expo $para - 1`
done
echo $para1
bash fun.sh 2
# the output should be 1

На самом деле я нашел решение здесь: Как мне сравнить, если моя переменная содержит символ новой строки в оболочке Script

if [ ${#str} -eq 0 ] 

Но мне интересно, достаточно ли он надежен или есть более элегантный способ сделать это?

1 Ответ

1 голос
/ 30 октября 2019

Пожалуйста, обратите внимание на код:

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», начиная с заданной позиции в обратном направлении.

Надеюсь, это поможет.

...