Как вы представляете EOF в bash?
Я пытаюсь сделать что-то вроде
read -d EOF stdin
for word in $stdin; do stuff; done
где я хочу заменить "EOF" на фактическое представление конца символа файла.
Изменить: Спасибо за ответы, это действительно то, что я пытался сделать. У меня на самом деле был момент facepalm, когда я увидел stdin=$(cat)
lol
Просто для пинков, но как бы вы хотели совместить что-то вроде C-d (или C-v M-v и т.д.), в основном просто персонаж в сочетании с Control, Alt, Shift, что угодно в bash?
Ответы
Ответ 1
На самом деле нет символа конца файла. Когда вы нажимаете Ctrl-d или аналогичные символы, драйвер терминала сигнализирует программе чтения, что конец файла достигнут, возвращая недопустимое значение. То же самое происходит с операционной системой, когда вы достигли конца файла. Это делается с использованием целого числа вместо байта (поэтому у вас есть диапазон, близкий к -2 ^ 16.. 2 ^ 16, а не только 0..255) и возврат значения вне диапазона - обычно -1
, Но нет символа, который будет представлять eof
, потому что его цель - не символ. Если вы хотите прочитать все, начиная с stdin, вплоть до конца файла, попробуйте
stdin=$(cat)
for word in $stdin; do stuff; done
Это, однако, прочитает весь стандартный ввод в переменную. Вы можете избавиться только от выделения памяти для одной строки с использованием массива и сделать read
чтение слов строки в этот массив:
while read -r -a array; do
for word in "${array[@]}"; do
stuff;
done
done
Ответ 2
Чтобы узнать, что такое управляющий символ, запустите
$ cat | od -b
^D
0000000 004 012
0000002
Я напечатал ^V ^D после выдачи команды, а затем RET и еще один ^D (без кавычек), и результатом является то, что EOF является восьмеричным номером 004.
Объединяя этот результат с read(1)
:
$ read -d "$(echo -e '\004')" stdin
foo
bar quuz^Hx
^D
$ echo "$stdin"
foo
bar quux
$ for word in $stdin; do echo $word; done
foo
bar
quux
Да, я набрал ^H выше для backspace, чтобы убедиться, что read(1)
сделал правильную вещь. Он делает.
Ответ 3
Две вещи...
Символ EOF представлен C-d (или C-v C-d, если вы хотите ввести его), но для того, чтобы делать то, что вы пытаетесь, лучше сделать это:
while read line; do stuff "${line}"; done
Ответ 4
litb и Даниил прав, я просто отвечу на ваш вопрос "Just for kick":
Bash (как любая программа командной строки командной строки вообще), только символы отображаются как байты. Таким образом, вы не можете сопоставить Alt-v, вы будете сопоставлять любые байты, отправленные вам из пользовательского интерфейса (псевдо-tty), которые интерпретируют эти нажатия клавиш у пользователей. Это могут быть даже сигналы unix, даже не байты. Это будет зависеть от используемой терминальной программы, настроек пользователя и всех видов вещей, поэтому я бы посоветовал вам не пытаться их сопоставить.
Но если вы знаете, что ваш терминал отправляет C-v в качестве байта 22 (0x16), вы можете использовать такие вещи, как:
if test "$char" = '^V'; then...
введя реальный ^ V char под ваш редактор (C-q C-v под emacs, C-v C-v под xterm,...), а не два символа ^ и V
Ответ 5
Мой собственный драйвер терминала, когда getc возвращает EOT, fclose stdout и снова открывается. Таким образом, когда считыватель getc воспринимает пустую очередь записи и возвращает значение EOF (не char), чтобы сигнализировать об этом, пользовательские подпрограммы, такие как `cat ', могут сдвинуть аргумент и в итоге выйти. Таким образом, EOF создает условие потока или маркер файла, не имеет значения в диапазоне `` char ''.