Eu tenho um programa UNIX de caixa preta usado em um shell Bash que lê colunas de dados de stdin, processa-as (aplicando um efeito de suavização) e depois produz para stdout. Eu o uso por pipes UNIX, como
generate | smooth | plot
Para mais suavização, posso repetir a suavização, para que seja invocada na linha de comando do Bash como
generate | smooth | smooth | plot
ou mesmo
generate | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | plot
Isso está ficando desagradável. Gostaria de criar um wrapper Bash para poder canalizar smooth
e alimentar sua saída de volta para uma nova instância de smooth
um número arbitrário de vezes, algo como
generate | newsmooth 5 | plot
ao invés de
generate | smooth | smooth | smooth | smooth | smooth | plot
Minha primeira tentativa foi um script Bash que gerou arquivos temporários no diretório atual e os excluiu, mas ficou feio quando eu não estava em um diretório com acesso de gravação e também deixou arquivos de lixo quando interrompidos.
Não há argumentos para o smooth
programa.
Existe uma maneira mais elegante de "encapsular" esse programa para parametrizar o número de chamadas?
fonte
Respostas:
Você pode envolvê-lo em uma função recursiva:
Você usaria isso como
o que seria equivalente a
fonte
Se você puder digitar tantas vírgulas quanto a quantidade de
smooth
comandos que desejar, poderá aproveitar a expansão Brace separada por vírgula do shell.TL; DR
A linha de comando inteira para o seu caso de amostra seria:
Nota:
smooth |
|
antes,plot
porque isso está incluído na últimasmooth |
string produzida pela Brace Expansionsmooth
, desde que possa incluí-los corretamente na parte fixa citada que precede a chave aberta; de qualquer forma, lembre-se de que você as forneceria a todas as repetições do comandoComo funciona
A expansão de cinta separada por vírgula permite produzir dinamicamente seqüências de caracteres, cada uma feita de uma parte fixa especificada mais as partes variáveis especificadas. Produz tantas seqüências quanto as partes variáveis indicadas, como
a{b,c,d}
produzab ac ad
.O pequeno truque aqui é que, se você preferir fazer uma lista de peças variáveis vazias , ou seja, com apenas vírgulas dentro dos aparelhos, a expansão de aparelho produzirá apenas cópias da peça fixa. Por exemplo:
vai produzir:
Observe que 4 vírgulas produzem 5
smooth
strings. É assim que essa expansão de cinta funciona: produz seqüências de caracteres tantas vírgulas quanto uma.É claro que, no seu caso, você também precisa
|
separar cada um delessmooth
, portanto, basta adicioná-lo na parte fixa, mas tenha o cuidado de citá-lo adequadamente para que o shell não o interprete de uma só vez. Isso é:vai produzir:
Sempre coloque a peça fixa imediatamente adjacente ao suporte aberto, ou seja, não há espaços entre o
'
e o{
.(Observe também que para formar a parte fixa, você também pode usar aspas duplas em vez de aspas simples, se precisar expandir variáveis de shell na parte fixa. Apenas cuide da fuga extra que é necessária quando ocorrem alguns caracteres especiais do shell dentro de uma sequência de aspas duplas).
Neste ponto, você precisa de uma
eval
aplicação aplicada a essa string para fazer com que o shell finalmente a interprete como o comando em pipeline que deveria ser.Portanto, para resumir tudo, toda a linha de comando do seu caso de amostra seria:
fonte
eval
quando se fornece seqüências de caracteres não confiáveis e não higienizadas para avaliação, ou seja, quando usado com variáveis que podem conter conteúdo "desconhecido", como o caso que você vinculou. Por outro lado,eval
também pode ser muito útil para o rápido "encanamento" de comandos, especialmente quando usado no prompt, como o caso em questão, ondeeval
a entrada de apenas seria uma string literal digitada manualmente pelo usuário em pessoaeval str
por algo pretensioso e estúpido. /dev/stdin <<<str
. Não só este vai fazer uma impressão em tolos, mas também irá manter @CharlesDuffy fora de sua volta ;-)