Eu quero canalizar a saída de um arquivo "template" para o MySQL, o arquivo tendo variáveis como ${dbName}
intercaladas. Qual é o utilitário de linha de comando para substituir essas instâncias e despejar a saída na saída padrão?
bash
command-line
text-processing
templating
Dana the Sane
fonte
fonte
cat
. Tudo que você precisa ésed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
.sed
espera-se um texto escapado, que é um aborrecimento.Atualizar
Aqui está uma solução da yottatsa em uma pergunta semelhante que substitui apenas variáveis como $ VAR ou $ {VAR} e é uma breve abordagem
É claro que se eu e o word estamos no seu ambiente, é apenas
No meu Mac, parece que ele foi instalado como parte do gettext e do MacGPG2
Resposta antiga
Aqui está uma melhoria para a solução do mogsie em uma pergunta semelhante: minha solução não exige que você escale aspas duplas, o mogsie faz, mas o dele é único!
O poder dessas duas soluções é que você obtém apenas alguns tipos de expansões de shell que não ocorrem normalmente $ ((...)), `...` e $ (...), embora a barra invertida seja uma aqui, mas você não precisa se preocupar com o fato de a análise ter um bug e executar várias linhas.
fonte
envsubst
não funciona se seus envares não forem exportados.envsubst
, como o nome sugere, reconhece apenas variáveis de ambiente , não variáveis de shell . Também vale a pena notar queenvsubst
é um utilitário GNU e, portanto, não está pré-instalado ou disponível em todas as plataformas.Use
/bin/sh
. Crie um pequeno script de shell que defina as variáveis e analise o modelo usando o próprio shell. Assim (edite para lidar com as novas linhas corretamente):Arquivo template.txt:
Arquivo script.sh:
Resultado:
fonte
bash
comando na entrada será executado. Se o modelo for: "as palavras são; rm -rf $ HOME", você perderá os arquivos.read
comando, conforme escrito, apara os espaços em branco à esquerda e à direita de cada linha e 'come'\
caracteres., (C) use somente se você confie ou controle a entrada, porque as substituições de comandos (`…`
ou$(…)
) incorporadas na entrada permitem a execução de comandos arbitrários devido ao uso deeval
. Finalmente, há uma pequena chance deecho
confundir o início de uma linha com uma de suas opções de linha de comando.Eu estava pensando sobre isso de novo, dado o interesse recente, e acho que a ferramenta em que estava pensando originalmente era
m4
o processador de macro para ferramentas automáticas. Então, em vez da variável especificada originalmente, você usaria:fonte
envsubst
para esse uso simples de substituição / modelagem de variáveis, conforme mencionado em outras respostas.m4
é uma ótima ferramenta, mas é um pré-processador completo com muito mais recursos e, portanto, complexidade que pode não ser necessária se você simplesmente quiser substituir algumas variáveis.template.txt
data.sh
parser.sh
parsed_file.txt
fonte
`…`
ou$(…)
) incorporadas na entrada permitem a execução de comandos arbitrários devido ao uso deeval
e a execução direta do código do shell devido ao uso desource
. Além disso, as aspas duplas na entrada são descartadas silenciosamente eecho
podem confundir o início de uma linha com uma de suas opções de linha de comando.Aqui está uma função Bash robusta que, apesar de ser usada,
eval
deve ser segura.Todas
${varName}
as referências de variáveis no texto de entrada são expandidas com base nas variáveis do shell de chamada.Nada mais é expandido: nem referências de variáveis cujos nomes não estão entre
{...}
(como$varName
), nem substituições de comandos ($(...)
e sintaxe herdada`...`
), nem substituições aritméticas ($((...))
e sintaxe herdada$[...]
).Para tratar a
$
como um literal,\
escape-o; por exemplo:\${HOME}
Observe que a entrada é aceita apenas via stdin .
Exemplo:
Código fonte da função:
A função assume que nenhuma
0x1
,0x2
,0x3
, e0x4
caracteres de controlo estão presentes na entrada, porque esses caracteres. são usados internamente - como a função processa o texto , isso deve ser uma suposição segura.fonte
eval
, é bastante seguro."
corretamente!)${FOO:-bar}
ou apenas produza algo se estiver definido -${HOME+Home is ${HOME}}
. Eu suspeito que com um pouco de extensão também pode retornar códigos de saída para variáveis faltando${FOO?Foo is missing}
, mas atualmente não tldp.org/LDP/abs/html/parameter-substitution.html tem uma lista de estes se isso ajudaCriar
rendertemplate.sh
:E
template.tmpl
:Renderize o modelo:
fonte
$(rm -rf ~)
, você o executará como código.eval "echo \"$(cat $1)\""
Funciona bem !aqui está minha solução com perl com base na resposta anterior, substitui as variáveis de ambiente:
fonte
Se você está aberto a usar Perl , essa seria minha sugestão. Embora haja provavelmente alguns especialistas em sed e / ou AWK que provavelmente sabem como fazer isso com muito mais facilidade. Se você tiver um mapeamento mais complexo com mais do que apenas dbName para suas substituições, poderá estendê-lo com bastante facilidade, mas é melhor colocá-lo em um script Perl padrão nesse momento.
Um script Perl curto para fazer algo um pouco mais complicado (manipular várias chaves):
Se você nomear o script acima como substituir-script, ele poderá ser usado da seguinte maneira:
fonte
Aqui está uma maneira de fazer com que o shell substitua você, como se o conteúdo do arquivo fosse digitado entre aspas duplas.
Usando o exemplo de template.txt com o conteúdo:
A linha a seguir fará com que o shell interpole o conteúdo do template.txt e grave o resultado no padrão.
Explicação:
i
eword
são passados como variáveis de ambiente incluídas na execução desh
.sh
executa o conteúdo da cadeia de caracteres pela qual é passada.echo "
' + "$(cat template.txt)
" + '"
'"
, "$(cat template.txt)
" se torna a saída decat template.txt
.sh -c
se torna:echo "The number is ${i}\nThe word is ${word}"
,i
eword
são as variáveis de ambiente especificadas.fonte
'$(rm -rf ~)'$(rm -rf ~)
as aspas literais no arquivo do modelo corresponderão às que você adicionou antes da expansão.'$(echo a)'$(echo a)
. Produz'a'a
. A principal coisa que está acontecendo é que a primeiraecho a
dentro da'
está sendo avaliada, o que pode não ser o que você espera desde que está presente'
, mas é o mesmo comportamento de incluir'
em uma"
sequência de caracteres citada."
string entre aspas (incluindo$(...)
) é o ponto.${varname}
, e não outras, expansões de alto risco à segurança.echo "
, seguida por uma string de aspas duplas com os contornos literais detemplate.txt
, seguida por outra string literal"
, todas concatenadas em um único argumento passado parash -c
. Você está certo que'
não pode ser correspondido (já que foi consumido pelo shell externo em vez de passado para o interno), mas"
certamente pode, portanto, um modelo contendoGotcha"; rm -rf ~; echo "
pode ser executado.file.tpl:
script.sh:
fonte
\$(date)
while IFS= read -r line; do
comoread
comando, caso contrário, você removerá os espaços em branco à esquerda e à direita de cada linha de entrada. Além disso,echo
pode confundir o início de uma linha com uma de suas opções de linha de comando, por isso é melhor usá-loprintf '%s\n'
. Finalmente, é mais seguro fazer aspas duplas${1}
.Sugiro usar algo como Sigil : https://github.com/gliderlabs/sigil
Ele é compilado em um único binário, por isso é extremamente fácil de instalar nos sistemas.
Em seguida, você pode fazer uma linha simples como a seguinte:
Isso é muito mais seguro
eval
e fácil do que usar regex oused
fonte
cat
e usar<my-file.conf.template
para fornecersigil
um identificador de arquivo real em vez de um FIFO.Eu encontrei este tópico enquanto me perguntava a mesma coisa. Isso me inspirou a isso (cuidado com os bastidores)
fonte
$(cat file)
is$(< file)
eval echo "\"$(cat FILE)\""
mas isso ainda pode não ser suficiente, pois as aspas duplas na entrada são descartadas.`…`
ou$(…)
) incorporadas na entrada permitem a execução de comandos arbitrários devido ao uso deeval
.Muitas opções aqui, mas achei que eu jogaria o meu na pilha. Ele é baseado em perl, segmenta apenas variáveis do formato $ {...}, pega o arquivo para processar como argumento e gera o arquivo convertido no stdout:
Claro que eu não sou realmente uma pessoa perl, então poderia facilmente haver uma falha fatal (funciona para mim).
fonte
Env::import();
linha - a importação está implícitause
. Além disso, sugiro não construir a saída inteira na memória primeiro: basta usar emprint;
vez de$text .= $_;
dentro do loop e soltar oprint
comando pós-loop .Isso pode ser feito no próprio bash se você tiver controle do formato do arquivo de configuração. Você só precisa originar (".") O arquivo de configuração, em vez de colocá-lo em um subconjunto. Isso garante que as variáveis sejam criadas no contexto do shell atual (e continuem a existir) em vez do subshell (onde a variável desaparece quando o subshell sai).
Se o seu arquivo de configuração não puder ser um script de shell, você pode simplesmente 'compilá-lo' antes de executá-lo (a compilação depende do seu formato de entrada).
No seu caso específico, você pode usar algo como:
Então canalize a saída do go.bash no MySQL e pronto, espero que você não destrua seu banco de dados :-).
fonte
go.bash
), você tem a ponta errada - eles não fazem parte da solução, são apenas uma maneira de mostrar que as variáveis estão sendo definido corretamente.Edição permanente de arquivos potencialmente múltiplos, com backups.
fonte