Eu tenho um arquivo de texto com o seguinte formato:
keyword value
keyword value
...
Onde palavra-chave é uma única palavra e valor é tudo o resto até o final da linha. Eu quero ler o arquivo de um script de shell, de maneira que os valores (mas não as palavras-chave) passem pela expansão do shell.
Com o sed, é fácil combinar as palavras-chave e as partes de valor
input='
keyword value value
keyword "value value"
keyword `uname`
'
echo "$input"|sed -e 's/^\([^[:space:]]*\)[[:space:]]\(.*\)$/k=<\1> v=<\2>/'
que produz
k=<keyword> v=<value value>
k=<keyword> v=<"value value">
k=<keyword> v=<`uname`>
mas a questão é como posso incorporar um comando shell na parte de substituição da expressão sed. Nesse caso, eu gostaria que a substituição fosse \1 `echo \2`
.
Respostas:
O sed padrão não pode chamar um shell (o GNU sed tem uma extensão para fazê-lo , se você se importa apenas com o Linux não incorporado), então você terá que fazer parte do processamento fora do sed. Existem várias soluções; todos requerem citações cuidadosas.
Não está claro exatamente como você deseja que os valores sejam expandidos. Por exemplo, se uma linha é
Qual das seguintes opções deve ser a saída?
Vou discutir várias possibilidades abaixo.
casca pura
Você pode fazer com que o shell leia a entrada de linha por linha e processe-a. Esta é a solução mais simples e também a mais rápida para arquivos curtos. Esta é a coisa mais próxima do seu requisito "
echo \2
":read -r keyword value
define$keyword
a primeira palavra da linha delimitada por espaços em branco e$value
o restante da linha menos o espaço em branco à direita.Se você deseja expandir referências de variáveis, mas não executar comandos fora das substituições de comandos, coloque
$value
dentro de um documento aqui . Eu suspeito que isso é o que você realmente estava procurando.sed canalizado em uma concha
Você pode transformar a entrada em um script de shell e avaliar isso. Sed está à altura da tarefa, embora não seja tão fácil. Seguindo o seu
echo \2
requisito " " (observe que precisamos escapar de aspas simples na palavra-chave):Indo com um documento aqui, ainda precisamos escapar da palavra-chave (mas de forma diferente).
Este é o método mais rápido se você tiver muitos dados: ele não inicia um processo separado para cada linha.
awk
As mesmas técnicas que usamos no sed trabalham com o awk. O programa resultante é consideravelmente mais legível. Indo com "
echo \2
":Usando um documento aqui:
fonte
Tendo o GNU,
sed
você pode usar o seguinte comando:Quais saídas:
com seus dados de entrada.
Explicação:
O comando sed suprime a saída regular usando a
-n
opção-r
é passado para usar expressões regulares estendidas, o que nos salva de alguns caracteres especiais no padrão, mas isso não é necessário.O
s
comando é usado para transferir a linha de entrada para o comando:A palavra-chave get citou o valor não. Eu passo a opção
e
- que é específica do GNU - para os
comando, que diz ao sed para executar o resultado da substituição como um comando shell e leio seus resultados no buffer de padrão (até várias linhas). O uso da opçãop
after (!)e
Torna ased
impressão do buffer padrão após a execução do comando.fonte
-n
ep
, por exemplosed -r 's/([^ ]+) (.*)/echo "\1" \2\n/e' input
. Mas obrigado por isso! Eu não sabia sobre ae
opção.e
opção (apresentada pelo GNU). Isso ainda ésed
? :)Você pode tentar esta abordagem:
(se eu acertar sua intenção). Ou seja, insira "processo" no início de cada linha não vazia para torná-lo um script como:
a ser avaliado (
eval
) onde processo é uma função que imprime a mensagem esperada.fonte
Se uma solução não sed for aceitável, este trecho de PERL fará o trabalho:
fonte
SOMENTE CURTO SED PURO CURTO
eu farei isso
e está funcionando.
fonte