EDIT: Por favor , por favor , leia os dois requisitos listados no final desta postagem antes de responder. As pessoas continuam postando suas novas joias, bibliotecas e outros enfeites, que claramente não atendem aos requisitos.
Às vezes eu quero hackear de forma muito barata algumas opções de linha de comando em um script simples. Uma maneira divertida de fazer isso, sem lidar com getopts ou parsing ou qualquer coisa assim, é:
...
$quiet = ARGV.delete('-d')
$interactive = ARGV.delete('-i')
...
# Deal with ARGV as usual here, maybe using ARGF or whatever.
Não é bem a sintaxe de opções Unix normal, porque aceitará parâmetros de linha de comando de opções não, como em " myprog -i foo bar -q
", mas posso viver com isso. (Algumas pessoas, como os desenvolvedores do Subversion, preferem isso. Às vezes eu também.)
Uma opção que está apenas presente ou ausente não pode ser implementada de forma muito mais simples do que a anterior. (Uma atribuição, uma chamada de função, um efeito colateral.) Existe uma maneira igualmente simples de lidar com opções que usam um parâmetro, como " -f
nome do arquivo "?
EDITAR:
Um ponto que eu não disse antes, porque não ficou claro para mim até que o autor de Trollop mencionou que a biblioteca cabia "em um arquivo [de 800 linhas]", é que não estou procurando apenas por sintaxe, mas para uma técnica que possui as seguintes características:
Todo o código pode ser incluído no arquivo de script (sem sobrecarregar o próprio script, que pode ter apenas algumas dezenas de linhas), de forma que se possa colocar um único arquivo em um
bin
diretório em qualquer sistema com um Ruby 1.8 padrão . [5-7] instalação e uso. Se você não pode escrever um script Ruby que não tenha instruções de requerimento e onde o código para analisar algumas opções tem menos de uma dúzia de linhas ou mais, você falhou neste requisito.O código é pequeno e simples o suficiente para que se possa lembrar o suficiente para digitar diretamente o código que fará o truque, em vez de cortar e colar de outro lugar. Pense na situação em que você está no console de um servidor com firewall sem acesso à Internet e deseja criar um script rápido para um cliente usar. Eu não sei sobre você, mas (além de falhar no requisito acima) memorizar até mesmo as 45 linhas do microoptparse simplificado não é algo que eu gostaria de fazer.
getoptlong
eoptparse
estão na biblioteca ruby padrão, então você NÃO PRECISA copiá-los ao implantar seu script - se o ruby funcionar nessa máquina, entãorequire 'optparse'
ourequire 'getoptlong'
funcionará também.Respostas:
Como autor de Trollop , não posso ACREDITAR as coisas que as pessoas acham que são razoáveis em um analisador de opções. Seriamente. Isso confunde a mente.
Por que devo fazer um módulo que estende algum outro módulo para analisar opções? Por que eu deveria ter que criar uma subclasse? Por que eu deveria assinar alguma "estrutura" apenas para analisar a linha de comando?
Aqui está a versão Trollop do acima:
E é isso.
opts
é agora um hash com chaves:quiet
,:interactive
e:filename
. Você pode fazer o que quiser com isto. E você obtém uma bela página de ajuda, formatada para caber na largura da sua tela, nomes de argumentos curtos automáticos, verificação de tipo ... tudo que você precisa.É um arquivo, então você pode soltá-lo em seu diretório lib / se não quiser uma dependência formal. Ele tem um DSL mínimo que é fácil de entender.
LOC por opção de pessoas. Importa.
fonte
Compartilho sua repulsa por
require 'getopts'
, principalmente devido à grandiosidade que éOptionParser
:fonte
Esta é a técnica padrão que costumo usar:
fonte
lib
pasta ou código e usá-lo sem nem mesmo tocar em rubygems.when /^-/ then usage("Unknown option: #{ARGV[0].inspect}")
parawhen /^-/ then usage("Unknown option: #{ARGV.shift.inspect}")
ou entraria em um loop de uso infinitoJá que ninguém apareceu para mencioná-lo, e o título se refere à análise de linha de comando barata , por que não deixar o interpretador Ruby fazer o trabalho por você? Se você passar no
-s
switch (em seu shebang, por exemplo), você obterá switches muito simples de graça, atribuídos a variáveis globais de uma única letra. Aqui está seu exemplo usando essa opção:E aqui está a saída quando eu salvo isso como
./test
e faço o chmod+x
:Veja
ruby -h
para detalhes.Isso deve ser tão barato quanto ele ganha. Ele levantará um NameError se você tentar uma opção como
-:
, portanto, há alguma validação aí. Claro, você não pode ter nenhuma opção após um argumento não-switch, mas se você precisa de algo sofisticado, você realmente deve usar no mínimo OptionParser. Na verdade, a única coisa que me irrita sobre essa técnica é que você receberá um aviso (se você os habilitou) ao acessar uma variável global não definida, mas ainda é falsey, por isso funciona muito bem para ferramentas descartáveis e rápidas scripts.Uma advertência apontada por FelipeC nos comentários em " Como fazer uma análise de opção de linha de comando realmente barata em Ruby ", é que seu shell pode não suportar o shebang de 3 tokens; você pode precisar substituir
/usr/bin/env ruby -w
pelo caminho real para o seu ruby (como/usr/local/bin/ruby -w
), ou executá-lo a partir de um script de invólucro, ou algo assim.fonte
Eu construí o microoptparse para preencher essa necessidade óbvia de um analisador de opções curto, mas fácil de usar. Ele tem uma sintaxe semelhante a Trollop e tem 70 linhas curtas. Se você não precisa de validações e pode ficar sem linhas vazias, você pode reduzir para 45 linhas. Acho que é exatamente isso que você estava procurando.
Pequeno exemplo:
Chamar o script com
-h
ou--help
imprimiráEle verifica se a entrada é do mesmo tipo que o valor padrão, gera acessadores curtos e longos, imprime mensagens de erro descritivas se argumentos inválidos são fornecidos e muito mais.
Eu comparei vários analisadores de opções usando cada analisador de opções para o problema que tive. Você pode usar esses exemplos e meu resumo para tomar uma decisão informativa. Sinta-se à vontade para adicionar mais implementações à lista. :)
fonte
optparse
(mais ou menos) 1937 linhas.optparse
é uma biblioteca padrão, ou seja, ela vem com todas as instalações do Ruby.Trollop
é uma biblioteca de terceiros, portanto, você deve importar o código completo toda vez que quiser incluí-lo em um projeto. µ-optparse sempre requer apenas ~ 70 linhas, uma vez queoptparse
já está lá.Eu entendo perfeitamente por que você deseja evitar optparse - pode ser demais. Mas existem algumas soluções muito mais "leves" (em comparação com o OptParse) que vêm como bibliotecas, mas são simples o suficiente para fazer uma única instalação gem valer a pena.
Por exemplo, verifique este exemplo OptiFlag . Apenas algumas linhas para o processamento. Um exemplo ligeiramente truncado sob medida para seu caso:
Também existem muitos exemplos personalizados . Lembro-me de usar outro que foi ainda mais fácil, mas me escapou por enquanto, mas voltarei e adicionarei um comentário aqui se eu encontrar.
fonte
Isso é o que eu uso para argumentos muito, muito baratos:
então, se você executá-
programname foo bar
lo, chama foo e bar. É útil para scripts descartáveis.fonte
Você pode tentar algo como:
fonte
Você já considerou Thor por wycats? Acho que é muito mais limpo do que optparse. Se você já tem um script escrito, pode dar mais trabalho formatá-lo ou refatorá-lo para o thor, mas torna as opções de manuseio muito simples.
Aqui está o snippet de exemplo do README:
Thor mapeia comandos automaticamente como:
Isso é convertido em:
fonte
--help
saída? E se "head myprogram.rb" fosse a saída de ajuda?Aqui está meu analisador de opções rápido e sujo favorito:
As opções são expressões regulares, portanto "-h" também corresponderia a "--help".
Legível, fácil de lembrar, sem biblioteca externa e código mínimo.
fonte
/-h(\b|elp)
Trollop é muito barato.
fonte
Se você deseja um analisador de linha de comando simples para comandos de chave / valor sem o uso de gems:
Mas isso só funciona se você sempre tiver pares de chave / valor.
Se você não precisa de nenhuma verificação, pode apenas usar:
fonte
Este é o snippet de código que uso na parte superior da maioria dos meus scripts:
Eu também odeio exigir arquivos adicionais em meus scripts rápidos e sujos. Minha solução é quase o que você está pedindo. Eu colo um trecho de código de 10 linhas no topo de qualquer um dos meus scripts que analisa a linha de comando e coloca args posicionais e muda para um objeto Hash (geralmente atribuído a um objeto que chamei de arghash nos exemplos abaixo).
Aqui está um exemplo de linha de comando que você pode querer analisar ...
Que se tornaria um Hash assim.
Além disso, dois métodos de conveniência são adicionados ao Hash:
argc()
retornará a contagem de argumentos não alternativos.switches()
devolverá um array contendo as chaves para os interruptores que estão presentesIsso significa permitir algumas coisas rápidas e sujas como ...
arghash.argc == 2
)arghash[1]
sempre obtém o segundo argumento não-switch).arghash['--max=']
qual produz um valor de '15' dada a linha de comando de exemplo.arghash['-s']
qual avalia como verdadeiro se estiver presente e nulo se estiver ausente.Teste a presença de um interruptor ou alternativas de interruptores usando operações definidas como
puts USAGETEXT if !(%w(-h --help) & arghash.switches()).empty?
Identifique o uso de interruptores inválidos usando operações definidas, como
puts "Invalid switch found!" if !(arghash.switches - %w(-valid1 -valid2)).empty?
Especifique os valores padrão para argumentos ausentes usando um simples
Hash.merge()
, como o exemplo abaixo que preenche um valor para -max = se um não foi definido e adiciona um 4º argumento posicional se um não foi passado.with_defaults = {'-max=' => 20, 3 => 'default.txt'}.merge(arghash)
fonte
=
) pode fazer a diferença no código de que você precisa.Isso é muito semelhante à resposta aceita, mas usando
ARGV.delete_if
qual é o que eu uso no meu analisador simples . A única diferença real é que as opções com argumentos devem estar juntas (por exemplo-l=file
).fonte
Aparentemente, @WilliamMorgan e eu pensamos da mesma forma. Acabei de lançar ontem à noite para o Github o que agora vejo é uma biblioteca semelhante ao Trollop (chamado como?) Depois de ter feito uma pesquisa por OptionParser no Github, consulte Switches
Existem algumas diferenças, mas a filosofia é a mesma. Uma diferença óbvia é que Switches depende de OptionParser.
fonte
Estou desenvolvendo minha própria gem de analisador de opções chamada Acclaim .
Eu o escrevi porque queria criar interfaces de linha de comando no estilo git e ser capaz de separar claramente a funcionalidade de cada comando em classes separadas, mas também pode ser usado sem a estrutura de comando inteira:
Ainda não há versão estável, mas já implementei alguns recursos como:
Há muita ênfase nos comandos, então pode ser um pouco pesado para a análise simples da linha de comando, mas funciona bem e tenho usado em todos os meus projetos. Se você estiver interessado no aspecto da interface de comando, verifique a página GitHub do projeto para obter mais informações e exemplos.
fonte
Suponha que um comando tenha no máximo uma ação e um número arbitrário de opções como este:
A análise sem validação pode ser assim:
fonte
https://github.com/soveran/clap
46LOC (em 1.0.0), sem dependência do analisador de opção externa. Faz o trabalho. Provavelmente não tão completo quanto os outros, mas é 46LOC.
Se você verificar o código, poderá facilmente duplicar a técnica subjacente - atribua lambdas e use o arity para garantir que o número adequado de argumentos siga a sinalização se você realmente não quiser uma biblioteca externa.
Simples. Barato.
EDIT : o conceito subjacente se resumiu, suponho que você pode copiar / colar em um script para fazer um analisador de linha de comando razoável. Definitivamente, não é algo que eu guardaria na memória, mas usar a lambda aridade como um analisador barato é uma ideia nova:
fonte
Vou compartilhar meu próprio analisador de opções simples no qual venho trabalhando há algum tempo. São apenas 74 linhas de código e fazem o básico do que o analisador de opções interno do Git faz. Tomei OptionParser como inspiração, e também do Git.
https://gist.github.com/felipec/6772110
Se parece com isso:
fonte
EasyOptions não requer nenhum código de análise de opção. Basta escrever o texto de ajuda, exigir, pronto.
fonte