Подтвердить что ты не робот

Как вы представляете 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?

4b9b3361

Ответ 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 ''.