ORD и CHR файл в Bash

Я строю ord а также chr функции, и они работают просто отлично. Но если я возьму файл, который содержит \n, например:

hello
CHECK THIS HIT
YES

когда я ord все, что я не получаю никаких новых значений строки. Это почему? Я пишу на Bash.

Вот код, который я использую:

function ord { 
    ordr="`printf "%d\n" \'$1`" 
}

TEXT="`cat $1`"
for (( i=0; i<${#TEXT}; i++ )) 
do 
    ord "${TEXT:$i:1}" 
    echo "$ordr" 
done

1 ответ

Решение

Ваш ord функция действительно странная. Возможно было бы лучше написать это как:

function ord { 
    printf -v ordr "%d" "'$1"
}

Тогда вы бы использовали его как:

TEXT=$(cat "$1")
for (( i=0; i<${#TEXT}; i++ )); do 
    ord "${TEXT:$i:1}" 
    printf '%s\n' "$ordr"
done

Это по-прежнему оставляет две проблемы: вы не сможете иметь нулевые байты и не будете видеть завершающие символы новой строки. Например (я назвал ваш сценарий banana а также chmod +x banana):

$ ./banana <(printf 'a\0b\n')
97
98

Здесь показаны две проблемы: нулевой байт удаляется из Bash в TEXT=$(cat "$1") часть, поскольку переменная Bash не может содержать нулевые байты. Кроме того, этот шаг также обрезает завершающие символы новой строки.

Более надежный подход будет использовать read:

while IFS= read -r -n 1 -d '' char; do
    ord "$char"
    printf '%s\n' "$ordr"
done < "$1"

С этой модификацией:

$ ./banana <(printf 'a\0b\n')
97
0
98
10

Обратите внимание, что этот скрипт будет зависеть от вашей локали. С моей локалью (LANG="en_US.UTF-8):

$ ./banana <(printf 'a\0ℂ\n')
97
0
8450
10

в то время как:

$ LANG= ./banana <(printf 'a\0ℂ\n')
97
0
226
132
130
10

Это показывает, что Bash читает не байты, а символы. Поэтому в зависимости от того, как вы хотите, чтобы Bash обрабатывал ваши данные, установите LANG соответственно.


Если ваш скрипт только это делает, гораздо проще не использовать ord функция вообще:

#!/bin/bash

while IFS= read -r -n 1 -d '' char; do
    printf '%d\n' "'$char"
done < "$1"

Это так просто!

Другие вопросы по тегам