bash: read: как записать символ '\ n' (новая строка)?

Обнаружены проблемы.

1: Том резервного копирования данных тонкого пула должен быть такого же или большего размера, что и базовое блочное устройство. Команда создания dd тома резервного копирования данных должна иметь тот же размер блока и "$ base_size", что и моя исходная привязка.

2: Вторым числом в определении таблицы команды dmsetup create thin_pool должно быть количество блоков блочного устройства, которое получается с помощью следующего кода:

my $base_stats = stat($base_file);
my $base_blocks = $base_stats->size / 512;

Наконец, команда для создания тонкого пула выглядит следующим образом:

system("dmsetup create vm-pool\
   --table \"0 $base_blocks thin-pool $meta_lodev $snap_lodev 2048 2048\"");
6
01.08.2017, 18:26
2 ответа

Чтобы прочитать 1 символ, используйте вместо этого -N, который всегда читает один символ и не выполняет $IFSобработку:

read -rN1 var

read -rn1читает одну запись до одного символа и по-прежнему выполняет $IFSобработку (, а новая строка имеет значение по умолчанию $IFS, что объясняет, почему вы получаете пустой результат, даже если вы читаете NUL -записи с разделителями ). Вы бы использовали его вместо этого, чтобы ограничить длину записи, которую вы читаете.

В вашем случае с записями с разделителями NUL -(с -d ''), IFS= read -d '' -rn1 varбудет работать так же, как bashв любом случае не может хранить символ NUL в своих переменных, поэтому printf '\0' | read -rN1 varоставит $varпустой и возвращает ненулевой статус выхода -.

Чтобы иметь возможность читать произвольные символы, включая NUL, вы должны использовать оболочку zshвместо синтаксиса:

read -k1 'var?Enter a character: '

(нет необходимости в -rили IFS=. Однако обратите внимание, что read -kсчитывает с терминала(kдля клавиши ; Опция zsh -kпредшествует bash и даже ksh93 -Nна десятилетия ). Для чтения со стандартного ввода используйтеread -u0 -k1).

Пример (здесь нажатие Ctrl+Пробел для ввода символа NUL):

$ read -k1 'var?Enter a character: '
Enter a character: ^@
$ printf '%q\n' $var
$'\0'

Обратите внимание, что для чтения символа , readможет потребоваться прочитать более одного байта. Если ввод начинается с первого байта многобайтового символа -, он будет считывать как минимум еще один байт, поэтому вы можете получить $var, содержащее что-то, что оболочка считает длиной больше 1, если ввод содержит последовательности байтов, не образующие допустимых символов.

Например, в локали UTF -8:

$ printf '\xfc\x80\x80\x80\x80XYZ' | bash -c 'read -rN1 a; printf "<%q>\n" "$a" "${#a}"; wc -c'
<$'\374\200\200\200\200X'>
<6>
2
$ printf '\xfc\x80\x80\x80\x80XYZ' | zsh -c 'read -u0 -k1 a; printf "<%q>\n" $a $#a; wc -c'
<$'\374'$'\200'$'\200'$'\200'$'\200'X>
<6>
2

В UTF -8, 0xFC — это первый байт символа длиной 6 -байтов, 5 других означают, что 8-й бит установлен, а 7-й бит не установлен, однако мы предоставляем только 4. readпо-прежнему читает этот дополнительный X, чтобы попытаться найти конец символа, который заканчивается в $var, вместе с теми 5 байтами, которые не образуют допустимый символ и в конечном итоге считаются одним символом каждый.

4
27.01.2020, 20:28

bashвстроенный readможет это сделать:

read -rd $'\0' -p... -n 1
printf '\nYou typed ASCII %02x\n' "'$REPLY"

(этот фрагмент кода не будет работать с многобайтовыми -символами)

Обратите внимание, что я не поместил прочитанное в переменную char, как это сделали вы. Это связано с тем, что это приведет к удалению символов в IFS из char. Со стандартным IFS вы не сможете различать пробел, табуляцию и новую строку.

5
27.01.2020, 20:28

Теги

Похожие вопросы