Как работает " кот
мне нужно написать скрипт для ввода многострочного ввода в программу (psql).
немного погуглив, я обнаружил, что работает следующий синтаксис:
cat << EOF | psql ---params
BEGIN;
`pg_dump ----something`
update table .... statement ...;
END;
EOF
это правильно строит многострочную строку (от BEGIN; до END;, включительно) и передает его как вход в psql.
но я понятия не имею, как/почему это работает, Может кто-нибудь объяснить?
я имею в виду в основном cat << EOF Я знаю > выводит в файл, >> дописывает в файл < считывает входные данные из файла.
что значит << точно?
и есть ли для этого страница man?
7 ответов:
это называется heredoc формат для предоставления строки в stdin. Смотрите https://en.wikipedia.org/wiki/Here_document#Unix_shells для более подробной информации.
С
man bash:Здесь Документы
этот тип перенаправления указывает оболочке на чтение входных данных из источник тока до линии содержит только слово (без трейлинга бланки) видно.
все строки, прочитанные до этого момента, затем используются в качестве стандартный ввод для команды.
формат здесь-документы:
<<[-]word here-document delimiterнет расширения параметров, замены команд, арифметического расширения или расширение пути выполняется на слово. Если какие-либо символы слово несколько цитирую: разделитель является результатом удаления цитаты на слово, а линии в здесь-документ не расширены. Если слово без кавычек, все строки здесь-документ подвергаются к расширению параметра, команде замена и арифметика расширение. В последнем случае последовательность символов
\<newline>is игнорируется, и\должен использоваться для цитирования символов\,$и`.если оператор перенаправления
<<-, то все ведущие символы табуляции удаляются из входных строк и строка, содержащая разделитель. Этот позволяет здесь-документы в сценариях оболочки должны быть отступы естественным образом.
The
cat <<EOFсинтаксис очень полезен при работе с многострочным текстом в Bash, например. при назначении многострочной строки переменной оболочки, файла или канала.примеры
cat <<EOFиспользование синтаксиса в Bash:1. Назначьте многострочную строку переменной оболочки
$ sql=$(cat <<EOF SELECT foo, bar FROM db WHERE foo='baz' EOF )The
$sqlпеременная теперь содержит символы новой строки тоже. Вы можете проверить с помощьюecho -e "$sql".2. Передать многострочную строку в файл внутри Баш
$ cat <<EOF > print.sh #!/bin/bash echo $PWD echo $PWD EOFThe содержит:
#!/bin/bash echo $PWD echo /home/user3. Пройти многострочные к трубе в bash
$ cat <<EOF | grep 'b' | tee b.txt foo bar baz EOFThe содержит
barиbazстроки. Тот же вывод выводится наstdout.
в вашем случае "EOF "известен как"здесь тег". В основном
<<Hereсообщает оболочке, что вы собираетесь ввести многострочную строку, пока "тег"Here. Вы можете назвать этот тег, как вы хотите, это частоEOFилиSTOP.некоторые правила о тегах здесь:
- тег может быть любой строкой, прописной или строчной, хотя большинство людей используют верхний регистр по соглашению.
- тег не будет рассматриваться как здесь тег, если есть другие слова в эта линия. В этом случае он будет просто считаться частью строки. Тег должен быть сам по себе на отдельной строке, чтобы считаться тегом.
- тег не должен иметь передних или конечных пробелов в этой строке, чтобы считаться тегом. В противном случае он будет рассматриваться как часть строки.
пример:
$ cat >> test <<HERE > Hello world HERE <-- Not by itself on a separate line -> not considered end of string > This is a test > HERE <-- Leading space, so not considered end of string > and a new line > HERE <-- Now we have the end of the string
POSIX 7
kennytm цитирует
man bash, но большинство из них также POSIX 7: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04:операторы перенаправления "
здесь-документ должен рассматриваться как одно слово, которое начинается после следующего и продолжается до тех пор , пока не появится строка, содержащая только разделитель и a, без символов между ними. Затем начинается следующий здесь-документ, если он есть. Формат выглядит следующим образом:
[n]<<word here-document delimiterгде необязательный n представляет номер дескриптора файла. Если номер опущен, то здесь-документ ссылается на стандартный ввод (дескриптор файла 0).
если какой-либо символ в слове заключен в кавычки, разделитель должен быть сформирован путем выполнения кавычки удаление по word, и строки здесь-документа не должны быть расширены. В противном случае разделителем будет само слово.
если никакие символы в word не заключены в кавычки, все строки здесь-документа должны быть расширены для расширения параметров, замены команд и арифметического расширения. В этом случае in input ведет себя как внутренние двойные кавычки (см. двойные кавычки). Однако символ двойной кавычки ( '"' ) не должен рассматриваться специально в данном документе, за исключением когда двойная кавычка появляется внутри "$()", "`", или" ${}".
если символ перенаправления "<tab> символы должны быть удалены из входных строк и строки, содержащей конечный разделитель. Если в строке указано более одного оператора "
когда здесь-документ читается из a терминальное устройство и оболочка являются интерактивными, они должны записывать содержимое переменной PS2, обработанной, как описано в переменных оболочки, до стандартной ошибки перед чтением каждой строки ввода до тех пор, пока разделитель не будет распознан.
примеры
некоторые примеры еще не приведены.
кавычки предотвращают расширение параметра
без кавычек:
a=0 cat <<EOF $a EOFвыход:
0С цитаты:
a=0 cat <<'EOF' $a EOFили (некрасиво, но действует):
a=0 cat <<E"O"F $a EOFвыходы:
$aдефис удаляет ведущие вкладки
без дефиса:
cat <<EOF <tab>a EOFздесь
<tab>- это литеральная вкладка, и ее можно вставить с помощьюCtrl + V <tab>выход:
<tab>aс дефисом:
cat <<-EOF <tab>a <tab>EOFвыход:
aэто существует конечно, так что вы можете в начале
catкак окружающие код, который легче читать и поддерживать. Например:if true; then cat <<-EOF a EOF fiк сожалению, это не работает для пробелов: POSIX favored
tabвдавливания здесь. Хлоп.
используя тройник вместо кота
не совсем как ответ на исходный вопрос, но я все равно хотел поделиться этим: мне нужно было создать файл конфигурации в каталоге, который требовал прав root.
в этом случае не работает следующее:
$ sudo cat <<EOF >/etc/somedir/foo.conf # my config file foo=bar EOFпотому что перенаправление обрабатывается вне контекста sudo.
Я в конечном итоге вместо этого:
$ sudo tee <<EOF /etc/somedir/foo.conf >/dev/null # my config file foo=bar EOF
это не ответ на исходный вопрос, но некоторые результаты моих собственных тестов. Это:
<<test > print.sh #!/bin/bash echo $PWD echo $PWD testсоздаст тот же файл, что и:
cat <<test > print.sh #!/bin/bash echo $PWD echo $PWD testИтак, я не вижу смысла использовать команду cat.
стоит отметить, что здесь Документы работают и в циклах bash. В этом примере показано, как получить список столбцов таблицы:
export postgres_db_name='my_db' export table_name='my_table_name' # start copy while read -r c; do test -z "$c" || echo $table_name.$c , ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}" SELECT column_name FROM information_schema.columns WHERE 1=1 AND table_schema = 'public' AND table_name =:'table_name' ; EOF ) # stop copy , now paste straight into the bash shell ... output: my_table_name.guid , my_table_name.id , my_table_name.level , my_table_name.seq ,или даже без новой строки
while read -r c; do test -z "$c" || echo $table_name.$c , | perl -ne 's/\n//gm;print' ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}" SELECT column_name FROM information_schema.columns WHERE 1=1 AND table_schema = 'public' AND table_name =:'table_name' ; EOF ) # output: daily_issues.guid ,daily_issues.id ,daily_issues.level ,daily_issues.seq ,daily_issues.prio ,daily_issues.weight ,daily_issues.status ,daily_issues.category ,daily_issues.name ,daily_issues.description ,daily_issues.type ,daily_issues.owner