linux - write - unix eof command
Como “cat<< EOF” funciona em bash? (5)
POSIX 7
kennytm citou man bash
, mas a maioria disso também é POSIX 7: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 :
Os operadores de redirecionamento "<<" e "<< -" permitem o redirecionamento de linhas contidas em um arquivo de entrada do shell, conhecido como "aqui-documento", para a entrada de um comando.
O documento aqui deve ser tratado como uma única palavra que começa após a próxima e continua até que haja uma linha contendo apenas o delimitador e a, sem caracteres intermediários. Então o próximo documento aqui começa, se houver um. O formato é o seguinte:
[n]<<word here-document delimiter
onde o opcional n representa o número do descritor de arquivo. Se o número for omitido, o documento here refere-se à entrada padrão (descritor de arquivo 0).
Se qualquer caractere na palavra for citado, o delimitador será formado pela remoção da cotação na palavra e as linhas do documento aqui não serão expandidas. Caso contrário, o delimitador será a própria palavra.
Se não houver caracteres na palavra, todas as linhas do documento here serão expandidas para expansão de parâmetros, substituição de comandos e expansão aritmética. Nesse caso, o na entrada se comporta como aspas duplas internas (consulte Double-Quotes). No entanto, o caractere de aspas duplas ('"') não deve ser tratado especialmente dentro de um documento aqui, exceto quando a aspa dupla aparecer dentro de" $ () "," `` "ou" $ {} ".
Se o símbolo de redirecionamento for "<< -", todos os caracteres iniciais de
<tab>
devem ser removidos das linhas de entrada e da linha que contém o delimitador final. Se mais de um operador "<<" ou "<< -" for especificado em uma linha, o documento aqui associado ao primeiro operador deverá ser fornecido primeiro pelo aplicativo e deverá ser lido primeiro pelo shell.Quando um documento aqui é lido de um dispositivo terminal e o shell é interativo, ele deve gravar o conteúdo da variável PS2, processada conforme descrito em Variáveis Shell, em um erro padrão antes de ler cada linha de entrada até que o delimitador seja reconhecido.
Exemplos
Alguns exemplos ainda não fornecidos.
Cotações impedem a expansão de parâmetros
Sem aspas:
a=0
cat <<EOF
$a
EOF
Saída:
0
Com aspas:
a=0
cat <<'EOF'
$a
EOF
ou (feio mas válido):
a=0
cat <<E"O"F
$a
EOF
Saídas:
$a
O hífen remove as guias principais
Sem hífen:
cat <<EOF
<tab>a
EOF
onde <tab>
é uma tabulação literal e pode ser inserida com Ctrl + V <tab>
Saída:
<tab>a
Com hífen:
cat <<-EOF
<tab>a
<tab>EOF
Saída:
a
Isso existe, é claro, para que você possa recuar seu cat
como o código circundante, que é mais fácil de ler e manter. Por exemplo:
if true; then
cat <<-EOF
a
EOF
fi
Infelizmente, isso não funciona para caracteres de espaço: POSIX favoreceu a indentação de tabulação aqui. Yikes
Eu precisava escrever um script para inserir entrada de várias linhas em um programa ( psql
).
Depois de um pouco de googling, encontrei os seguintes trabalhos de sintaxe:
cat << EOF | psql ---params
BEGIN;
`pg_dump ----something`
update table .... statement ...;
END;
EOF
Isso constrói corretamente a cadeia de várias linhas (de BEGIN;
para END;
inclusive) e canaliza-a como uma entrada para o psql
.
Mas eu não tenho ideia de como / porque funciona, alguém pode explicar por favor?
Estou me referindo principalmente a cat << EOF
, eu sei >
saídas para um arquivo, >>
acrescenta a um arquivo, <
lê a entrada do arquivo.
O que exatamente <<
faz?
E há uma página de homem para isso?
A sintaxe cat <<EOF
é muito útil quando se trabalha com texto de várias linhas no Bash, por exemplo. ao atribuir string de várias linhas a uma variável, arquivo ou pipe.
Exemplos de uso de sintaxe cat <<EOF
no Bash:
1. Atribuir cadeia de várias linhas a uma variável de shell
$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)
A variável $sql
agora também contém os caracteres de nova linha. Você pode verificar com echo -e "$sql"
.
2. Passe uma string de várias linhas em um arquivo no Bash
$ cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF
O arquivo print.sh
agora contém:
#!/bin/bash
echo $PWD
echo /home/user
3. Passe uma string de várias linhas em um pipe no Bash
$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF
O arquivo b.txt
contém linhas bar
e baz
. A mesma saída é impressa no stdout
.
Isso não é necessariamente uma resposta à pergunta original, mas um compartilhamento de alguns resultados dos meus próprios testes. Este:
<<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test
irá produzir o mesmo arquivo como:
cat <<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test
Então, não vejo o ponto de usar o comando cat.
No seu caso, "EOF" é conhecido como "Here Tag". Basicamente <<Here
diz ao shell que você vai inserir uma string de múltiplas linhas até a "tag" Here
. Você pode nomear essa tag como quiser, geralmente é EOF
ou STOP
.
Algumas regras sobre as tags Here:
- A tag pode ser qualquer string, maiúscula ou minúscula, embora a maioria das pessoas use maiúsculas por convenção.
- A tag não será considerada como uma tag Here se houver outras palavras nessa linha. Nesse caso, ele será considerado apenas parte da string. A tag deve estar em uma linha separada para ser considerada uma tag.
- A tag não deve ter espaços iniciais ou finais nessa linha para ser considerada uma tag. Caso contrário, será considerado como parte da string.
exemplo:
$ 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
Usando tee em vez de gato
Não exatamente como uma resposta à pergunta original, mas eu queria compartilhar isso de qualquer maneira: eu tinha a necessidade de criar um arquivo de configuração em um diretório que exigisse direitos de root.
O seguinte não funciona para esse caso:
$ sudo cat <<EOF >/etc/somedir/foo.conf
# my config file
foo=bar
EOF
porque o redirecionamento é tratado fora do contexto do sudo.
Acabei usando isso em vez disso:
$ sudo tee <<EOF /etc/somedir/foo.conf >/dev/null
# my config file
foo=bar
EOF