LINUX.ORG.RU
ФорумAdmin

EOF, шелл, cat и варианты перенаправлений ввода и вывода

 , , перенаправление ввода, , стандартные потоки


0

1

Сам я часто пользуюсь

cat > file

для создания файла вставкой из буфера обмена.

После вставки пользуюсь Ctrl+D, чтобы передать cat EOF.

(Кстати, почему временами достаточно одинарного ^D, а иногда нужен двойной? - от того как иной раз маркер EOF попадает в буфер обмена?)


Потом, видел такой синтаксис в инструкциях:

cat << 'EOF' >  file

Как то, здесь: https://paulgorman.org/technical/asterisk-debian-lxc.txt.html

Как вторым вариантом пользоваться и чего он должен достигать мне не ясно: при таком синтаксисе судя по > на каждой строке я остаюсь в шелле не попадая в cat (как если ввести \ в конце строки, только без реакции на дальнейший Enter), и действия от Ctrl+D нет: если остановить по Ctrl+C, то в file ничего из введённого закономерно не остаётся.


Может ли кто-то внести ясность?

Перемещено hobbit из general

★★★★★

Последнее исправление: eugrus (всего исправлений: 1)

Кстати, почему временами достаточно одинарного ^D, а иногда нужен двойной?

Это когда это?

cat <<EOF

Тут буквы EOF — это просто условность и вместо EOF могут быть любые буквы, почитай как работает bash heredoc.

t184256 ★★★★★
()

Не знаю, правильно ли вы понимаете EOF. Для процесса EOF — это не символ, а событие, системный вызов read() вернул 0 байт. Ctrl+D от терминала уходит в ядро, а ядро делает процессу, читающему с терминала событие EOF.

Синтаксис в инструкция — это ″Here Document″ (man bash) и там вместо EOF может быть любое слово и это предназначено для скриптов, чтобы там можно было легко многострочные текстовые блоки отправлять на stdin процесса. И, да, при вызове here-doc из командной строки, вы остаётесь в шелле, процесс (cat) будет запущен как команда будет распарсена до конца (после ввода закрывающего EOF).

Для меня инструкции, в которых советуют заполнять файл через cat, — это какая-то дичь. Не важно, будет там cat + Ctrl+D или cat + here-doc. Инструкция должна просто приводить содержимое файла, а уж как его создавать дело читателя инструкции.

По вашей ссылки вобще какая-то ерунда, или у меня браузер неправильно отображает, там в here-doc форматирование съехавшее. Ну и инструкции, в которые насован sed тоже дичь, не все понимают смысл команды sed, и если она отработает криво, даже не будут знать, что должно быть в файле. У тогда вместо такой инструкции давать скрипт, который и правит и проверяет, что в конфиге появился параметрс с исправленым значением.

mky ★★★★★
()
Ответ на: комментарий от eugrus

Это не совсем ESC-последовательность. ESC-последовательность — это команда терминалу (эмулятору терминала если в GUI). А это просто байт, код у него 4 (0x04), так как D это четвёртая буква алфавита. То есть эмулятор терминала отправляет в ядро байт 0x04. Ядро (драйвер tty) его обрабатывает и создаёт EOF. А для байта 0x03 (Ctrl-C) ядро отправить SIGINT.

Но, если вдруг ядро сглючит, или в настройках терминала для EOF будет другой код, а 0x04 не будет иметь специального значения, в общем, если ядро «выплюнет» этой байт в терминал, в stdin процесса, то там это будет просто байт. Он вернётся из функции read(), да и из функции чтения с потока (допустим getch()) тоже вернётся, просто как байт. getch() может вернуть EOF, но это не байт (char), а несколько байт (int), вот такой вот хак.

https://owengage.com/writing/2023-04-08-getting-the-ctrl-d/

На всякий случай тут напишу, что здесь речь про Юниксы, где есть понятие «терминал», именно на уровне системы. К какому-нибудь plan9 или ещё чему, описаное здесь не применимо. В линукс, в GUI эмулятор терминала (допустим xterm) взаимодействует с ядром через /dev/tmux, а запущеный в этом терминале процесс получает /dev/pts/XY и вобще не знает про xterm. То есть xterm ничего не пишет на stdin процесса cat и ничего не читает из его stdout, этим занимается ядро. Ядро реализует терминал — обработку кодов Ctrl+... , raw или canonical режим (построчную буферизацию), отправку SIGHUP при закрытии и т.д.

mky ★★★★★
()
Ответ на: комментарий от eugrus

Один раз Ctrl+D нужно нажимать в начале строки (то есть Enter, Ctrl+D). Если курсор не в начале строки, то первый Ctrl+D скидывает строку из буфера в stdin процесса и read() процесса вернёт эти данные, а уже второй будет EOF. Это POSIX. https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html

EOF
Special character on input, which is recognized if the ICANON flag is set. When received, all the bytes waiting to be read are immediately passed to the process without waiting for a <newline>, and the EOF is discarded. Thus, if there are no bytes waiting (that is, the EOF occurred at the beginning of a line), a byte count of zero shall be returned from the read(), representing an end-of-file indication. If ICANON is set, the EOF character shall be discarded when processed. NL

Если у вас в начале строки нужно дважды нажимать Ctrl+D — это явно глюки (клавиатуры, терминала, ядра...)

mky ★★★★★
()
Ответ на: комментарий от mky

Для меня инструкции, в которых советуют заполнять файл через cat, — это какая-то дичь. Не важно, будет там cat + Ctrl+D или cat + here-doc.

Использовать cat для заполнения файла можно только при незнании о существовании tee. Ну и да, может тебе будет заполнить файл с использованием ed удобнее.

Werenter ★★★
()
Ответ на: комментарий от eugrus

tee - read from standard input and write to standard output and files

Во всё, что читает stdin можно ввести вручную. Так-как tee сам открывает файл, то все любители sudo им очень довольны :)

mky ★★★★★
()
Ответ на: комментарий от mky

… Если у вас в начале строки нужно дважды нажимать Ctrl+D

Наоборот, если курсор находится в начале строки, то достаточно одиночного нажатия Ctrl+D. А вот если вы уже ввели какие-то символы, но не жмякнули на ENTER, то тогда требуется двойное нажатие Ctrl+D: по первому нажатию завершится висящая в cat операция READ и программа обработает последние введенные в теминале данные; по-второму нажатию операция READ в cat завершится с признаком конца файла (ну т. е. получит нулевую длину данных) и завершит свою работу.

Это легко проверить и увидеть, если просто запустить cat без параметров.

vinvlad ★★
()
Ответ на: комментарий от vinvlad

Хорошо, что вы не ТС, у него нет таких проблем в восприятием длинных фраз. Плохо представляю, как вам живётся, если вы не воспринимаете сложные предложения, игнорируете начало поста, на который отвечаете, целиком фокусируясь на половине фразы.

И не надо перевирать POSIX. ″read()″, а не ″операция READ″.

mky ★★★★★
()