Как "кошка
мне нужно написать скрипт для ввода многострочного ввода в программу (psql
).
после немного гуглить, я нашел следующие синтаксические работы:
cat << EOF | psql ---params
BEGIN;
`pg_dump ----something`
update table .... statement ...;
END;
EOF
это правильно создает многострочную строку (от BEGIN;
to END;
включительно) и трубы его в качестве вклада в psql
.
но я понятия не имею, как/почему это работает, Может кто-нибудь объяснить?
я имею в виду в основном cat << EOF
Я знаю >
вывод в файл, >>
дописывает в файл <
считывает входные данные из файла.
что значит <<
точно?
и есть ли для этого страница?
7 ответов
это называется помощи heredoc формат для предоставления строки в stdin. Вижу https://en.wikipedia.org/wiki/Here_document#Unix_shells для более подробной информации.
С man bash
:
Здесь Документы
этот тип перенаправления инструктирует оболочку считывать входные данные из источник тока до строки содержит только слово (без трейлинга холостые) видно.
все строки, прочитанные до этой точки, затем используются в качестве стандартный ввод для команды.
формат здесь-документы:
<<[-]word here-document delimiter
отсутствие расширения параметра, замены команды, арифметического расширения, или расширение пути выполняется на слово. Если какие-либо символы слово несколько цитирую: разделитель является результатом удаления цитаты на слово, а линии в здесь-документ не расширены. Если слово без кавычек, все строки здесь-документ подвергаются к расширению параметра, команде замена и арифметика расширение. В последнем случае последовательность символов
\<newline>
is игнорируется, и\
необходимо цитата символы\
,$
и`
.если оператор перенаправления
<<-
, то все ведущие символы табуляции удаляются из входных строк и строка, содержащая разделитель. Этот позволяет здесь-документы в сценариях оболочки должны быть отступами естественным образом.
на cat <<EOF
синтаксис очень полезен при работе с многострочным текстом в Bash, например. при назначении многострочной строки переменной оболочки, файлу или каналу.
примеры cat <<EOF
использование синтаксиса в Bash:
1. Назначьте многострочную строку переменной оболочки
$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)
на $sql
переменная теперь содержит символы новой строки. Вы можете проверить с помощью echo -e "$sql"
.
2. Передать многострочную строку в файл в Баш
$ cat <<EOF > print.sh
#!/bin/bash
echo $PWD
echo $PWD
EOF
на содержит:
#!/bin/bash
echo $PWD
echo /home/user
3. Передайте многострочную строку трубе в Bash
$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF
на содержит 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> символы должны быть удалены из входных строк и строки, содержащей конечный разделитель. Если в строке указано более одного оператора "
когда здесь-документ считывается из терминальное устройство и оболочка интерактивны, он должен записать содержимое переменной 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
вдавливания здесь. Хлоп.
использование tee вместо cat
не совсем как ответ на исходный вопрос, но я все равно хотел поделиться этим: мне нужно было создать файл конфигурации в каталоге, который требует прав 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