Eu notei muitas perguntas, respostas e comentários expressando desdém por (e às vezes até medo de) escrever scripts em vez de frases simples. Então, eu gostaria de saber:
Quando e por que devo escrever um script independente em vez de um "one-liner"? Ou vice-versa?
Quais são os casos de uso e os prós e contras de ambos?
Algumas linguagens (por exemplo, awk ou perl) são mais adequadas para one-liners do que outras (por exemplo, python)? Se sim, por quê?
É apenas uma questão de preferência pessoal ou existem boas razões (ou seja, objetivas) para escrever uma ou outra em circunstâncias particulares? Quais são esses motivos?
Definições
one-liner
: qualquer sequência de comandos digitados ou colados diretamente em uma linha de comando do shell . Muitas vezes envolvendo oleodutos e / ou uso de linguagens comosed
,awk
,perl
, e / ou ferramentas comogrep
oucut
ousort
.É a execução direta na linha de comando que é a característica definidora - o comprimento e a formatação são irrelevantes. Um "one-liner" pode estar todo em uma linha ou pode ter várias linhas (por exemplo, sh para loop ou código awk ou sed incorporado, com feeds de linha e recuo para melhorar a legibilidade).
script
: qualquer sequência de comandos em qualquer idioma interpretado que é salvo em um arquivo e, em seguida, executado. Um script pode ser escrito inteiramente em um idioma ou pode ser um wrapper de script de shell em vários "one-liners" usando outros idiomas.
Eu tenho minha própria resposta (que postarei mais tarde), mas quero que isso se torne uma sessão de perguntas e respostas canônicas sobre o assunto, não apenas minha opinião pessoal.
Respostas:
Outra resposta baseada na experiência prática.
Eu usaria uma linha só se fosse um código "descartável" que eu pudesse escrever diretamente no prompt. Por exemplo, eu posso usar isso:
Eu usaria um script se decidisse que valia a pena salvar o código. Nesse ponto, eu adicionaria uma descrição na parte superior do arquivo, provavelmente adicionaria alguma verificação de erro e talvez até a verificasse em um repositório de código para obter versões. Por exemplo, se eu decidisse que verificar o tempo de atividade de um conjunto de servidores era uma função útil que eu usaria repetidamente, o one-liner acima pode ser expandido para isso:
Generalizando, pode-se dizer
One-liner
Roteiro
cron
)Vejo um número razoável de perguntas aqui no unix.SE solicitando que uma única linha execute uma tarefa específica. Usando meus exemplos acima, acho que o segundo é muito mais compreensível que o primeiro e, portanto, os leitores podem aprender mais com ele. Uma solução pode ser facilmente derivada da outra, portanto, no interesse da legibilidade (para futuros leitores), provavelmente devemos evitar fornecer código compactado em uma linha para qualquer outra coisa que não seja a mais trivial das soluções.
fonte
set -- host1 host2 host3
, em seguida,for h in "$@"
(ou apenasfor h
), o que tornaria o script POSIX-portátil. :-)Escreva um script quando:
Escreva uma linha quando:
fonte
Quando uma série necessária de comandos é bastante curta e / ou produz um resultado que pode ser usado como parte de um pipeline maior ou de um alias de comando, pode ser uma boa opção.
Basicamente, acho que one-liners geralmente são coisas que um administrador de sistema experiente, familiarizado com o problema e com os comandos usados, pode escrever no local, sem pensar demais.
Quando um one-liner se torna excessivamente longo ou envolve mais do que condicionais ou loops muito simples, geralmente é melhor escrevê-los como um script de várias linhas ou função de shell, para facilitar a leitura. Além disso, se for algo que você escreve para ser usado repetidamente, ou algo que será usado (e possivelmente relacionado a problemas) por outras pessoas, você deve dedicar algum tempo para escrever a solução em um comentário mais claro, formulário de script.
No Python, a indentação faz parte da sintaxe; portanto, você literalmente não pode usar os recursos da linguagem em toda a extensão se escrever uma linha.
As linhas de comando perl e awk costumam usar o poder bruto das expressões regulares. Mas alguns chamam as expressões regulares de linguagem somente gravação, não inteiramente sem razão. Escrever um script de várias linhas permite escrever comentários para descrever o que uma expressão regular específica deve estar fazendo, o que será muito útil quando você olhar o script novamente, depois de fazer outras coisas por seis meses.
Essa é uma questão inerentemente muito baseada em opiniões, pois envolve a avaliação da quantidade de complexidade aceitável e as vantagens e desvantagens entre legibilidade e compacidade; tudo isso é muito questão de julgamento pessoal. Até a escolha de um idioma pode depender de assuntos pessoais: se um idioma em particular seria ideal para um problema em particular, mas você não o conhece e já sabe como resolver o problema com outro idioma, pode escolher a opção linguagem familiar para concluir o trabalho rapidamente e com o mínimo de esforço, embora a solução possa ser tecnicamente um pouco ineficiente.
O melhor é muitas vezes o inimigo do bom o suficiente , e isso se aplica muito aqui.
E se você conhece o Perl, já deve ter ouvido falar do TMTOWTDI: Há mais de uma maneira de fazer isso.
fonte
Por favor, note que esta é uma opinião pessoal; tomá-lo com um grão de sal.
Se o comando se encaixar em, digamos, 80 caracteres, use uma linha. É difícil trabalhar com linhas de comando longas. Há também o problema da recorrência, veja # 2
Se você precisar executar o (s) comando (s) mais de uma vez, use um script. Caso contrário, use uma linha, desde que a condição nº 1 seja atendida.
fonte
Visualizo e uso um one-liner como uma ferramenta de desenvolvimento temporária para editar repetidamente até que faça o que eu quero, ou entendo como funciona uma sutileza de um subcomando.
Em seguida, ele é anotado (e anotado) em um arquivo de texto sobre o assunto que eu estava investigando ou limpo em um script que é colocado na minha caixa pessoal PATH, possivelmente para aperfeiçoamento, parametrização e assim por diante. Normalmente, a única linha será dividida em mais legível, mesmo que nenhuma outra alteração seja feita ou se eu nunca mais usar o script.
Defino meu histórico de shell para mais de 5000 linhas, com um histórico separado por terminal e por login em um controle remoto e assim por diante. Detesto não poder encontrar nessas histórias um comando de uma linha que desenvolvi há algumas semanas e não achei que fosse necessário novamente, daí a minha estratégia.
Às vezes, um grupo inteiro de comandos precisa fazer algo, como configurar algum hardware; no final, copio todos eles do histórico, limpo-os minimamente e os adiciono a um script de shell
RUNME
apenas como notas sobre o que fiz, mas também para que estejam quase prontos para serem usados novamente por outra pessoa. (É por isso que encontro ferramentas que fornecem apenas uma interface gráfica do usuário para configurá-las de tal maneira.) Acho isso um ganho incrível em eficiência, pois muitas vezes algo que você espera fazer apenas uma vez deve ser feito mais 5 vezes. .fonte
ln
vs.ln -s
links diretos vs. soft em uma linha que faz um loop em alguns arquivos.Eu gostaria que as pessoas da minha equipe escrevessem scripts para quaisquer operações que possam ser necessárias para serem executadas mais de uma vez (ou seja, "fluxos de trabalho" ou "pipelines") e para qualquer tarefa pontual que seja exigida para ser documentada (normalmente coisas como "modificar certas coisas em alguns conjuntos de dados para corrigir dados fornecidos incorretamente" (no nosso caso). Além disso, "one-liners" ou scripts não importam muito.
A falta de documentação adequada dos fluxos de trabalho (como scripts ou equivalente) dificulta a introdução de novas equipes em um projeto e também a transição das pessoas para fora de um projeto. Além disso, dificulta qualquer tipo de auditoria, e o rastreamento de erros pode ser impossível.
Isso independentemente da linguagem usada para a programação.
Outros locais de trabalho podem ter costumes ou expectativas semelhantes / diferentes, talvez até anotados.
Em casa, você faz o que quiser.
Por exemplo, escrevo scripts assim que faço algo não trivial no shell, como antes de enviar uma resposta a uma pergunta de U&L ou sempre que preciso testar os componentes individuais de um comando ou conjunto de comandos antes de executá-lo "para real".
Também escrevo scripts para tarefas repetitivas que realmente quero sempre da mesma maneira, mesmo que sejam simples, como
Uso funções de shell (raramente aliases) para conveniência em shells interativos, por exemplo, para adicionar opções a certos comandos por padrão (
-F
parals
) ou para criar variações especializadas de alguns comandos (pman
aqui está umman
comando que apenas analisa os manuais do POSIX, por exemplo) .fonte
Parece que tenho uma opinião minoritária sobre isso.
O termo "script" é intencionalmente confuso, livre-se dele. Este é um software que você está escrevendo lá, mesmo se estiver usando apenas
bash
eawk
.Dentro de uma equipe, prefiro escrever software com o processo de revisão de código imposto por uma ferramenta (github / gitlab / gerrit). Isso fornece controle de versão como um bônus. Se você tiver vários sistemas, adicione ferramentas de implantação contínua. E alguns conjuntos de testes, se os sistemas de destino forem importantes. Eu não sou religioso sobre isso, mas peso os benefícios e custos.
Se você possui uma equipe de administradores, o mais simples
vim /root/bin/x.sh
é principalmente um desastre em termos de comunicação relacionada à mudança, legibilidade do código e distribuição entre sistemas. Muitas vezes, um mau funcionamento sério custa mais tempo / dinheiro do que o processo supostamente "pesado".I prefer one-liners , na verdade, para qualquer coisa que não merece esse processo "pesado". Eles podem ser reutilizados rapidamente, com algumas teclas, se você souber como usar seu histórico de shell com eficiência; colado facilmente entre sistemas não relacionados (por exemplo, clientes diferentes).
Diferença crucial entre os one-liners (não revisados!) E o software analisado ("scripts"): a responsabilidade é totalmente sua quando você executa os one-liners. Você nunca pode dizer para si mesmo "Acabei de encontrar essa linha em algum lugar, executei-a sem entender, o que se segue não é minha culpa" - você sabia que estava executando um software não revisado e não testado, por isso é sua culpa. Certifique-se de que seja pequeno o suficiente para que você possa prever os resultados - que se dane.
Às vezes, você precisa dessa abordagem simplista e definir a barra em cerca de uma linha de texto funciona bem na prática (ou seja, o limite entre o código revisado e o não revisado). Algumas de minhas falas parecem terrivelmente longas, mas funcionam efetivamente para mim. Desde que eu os goste e não os empurre para colegas mais jovens, tudo bem. No momento em que preciso compartilhá-los - eu passo pelo processo padrão de desenvolvimento de software.
fonte
Devo dizer que estou um pouco horrorizado com as implicações das primeiras partes da pergunta. As linguagens de script Unix são linguagens de programação completas, e linguagens de programação são linguagens , o que significa que são tão infinitamente maleáveis e flexíveis quanto as linguagens humanas. E uma das características da "maleabilidade e flexibilidade infinitas" é que quase nunca existe uma "maneira certa" de expressar algo - existem várias maneiras, e isso é uma coisa boa! Então, sim, é claro que é uma questão de preferência pessoal, e não há nada de errado nisso. Quem diz que há apenas uma maneira de fazer alguma coisa,
Era uma vez, a minha própria
~/bin
era cheia de pequenos scripts "úteis" que eu tinha escrito. Mas percebi que a maioria deles se acostumou no dia em que os escrevi e nunca mais. Portanto, quanto mais tempo passa, menor o meubin
diretório.Eu não acho que haja algo errado em escrever um script. Se você imagina que você ou outra pessoa pode usá-lo novamente, escreva um script. Se você deseja "projetar adequadamente" um script suportável, por todos os meios, faça-o. (Mesmo que ninguém nunca use, escrever é uma boa prática.)
Razões pelas quais não escrevo mais scripts (e, acho, favorecem "one-liners"):
bin
a desordem de diretório tem um custo. Eu não coloco as coisas mais lá, a menos que elas realmente pertençam a ela.fonte
Acredito que na maioria das vezes o pedido de "uma linha" seja de fato um pedido de "mordida de som", ou seja:
As pessoas desejam e solicitam o código mais curto que demonstre uma solução para a pergunta.
Às vezes, não há como reduzir um discurso a uma "mordida no som", assim como pode ser impossível reduzir um script a um "one-liner" curto. Nesses casos, a única resposta possível é um script.
E, em geral, uma "mordida no som" nunca é um bom substituto de todo o discurso. Portanto, um "one liner" geralmente é bom apenas para transmitir uma idéia ou para dar um exemplo prático dessa idéia. Depois que a ideia for entendida, ela deverá ser expandida (aplicada) em um script.
Então, escreva uma "linha única" para transmitir uma ideia ou conceito.
Escreva seu código geral como scripts completos, não one-liners.
fonte
Você pergunta sobre "medo e desdém de scripts". Isso ocorre devido à situação de perguntas e respostas, onde muitas vezes a resposta está dizendo: Ele precisa dessa etapa e da seguinte, mas também posso colocá-la em uma linha (para que você possa copiar, colá-lo e usá-lo como um longo e simples comando).
Às vezes, você pode apenas adivinhar se o Q é melhor atendido por uma solução de colar de cópia rápida e suja ou se um script "legal" é exatamente o que o Q precisa entender.
Muitos dos prós e contras aqui são verdadeiros, mas ainda estão perdendo o sentido. Eu diria mesmo que as definições no Q não são úteis.
Os arquivos de histórico do shell são "one liners", mas ainda são salvos. A função bash
operate-and-get-next (C-o)
ainda permite que você as repita de forma semi-automática.Quase não vejo a palavra função mencionada. Essa é a maneira de armazenar "scripts" e "one liners". E com algumas teclas, você pode alternar entre os dois formatos. Um comando composto geralmente pode ser compatível com ambos.
history -r file
é a maneira de ler uma ou várias linhas de comando (e comentários) de qualquer arquivo, não apenas do arquivo de histórico padrão. É preciso apenas uma organização mínima. Você não deve confiar em um tamanho grande de arquivo de histórico e na pesquisa de histórico para recuperar (algumas) versões de uma linha de comando.As funções devem ser definidas de maneira semelhante. Para iniciantes, coloque
thisfunc() {...}
em um arquivo "funções" em seu diretório pessoal e faça a origem dele. Sim, isso é uma sobrecarga, mas é a solução geral.Se você armazenar todas as linhas de comando e todas as variações de script em um arquivo separado, será um desperdício (teórico, mas objetivo) de blocos do sistema de arquivos.
Um one-liner não tem nada rápido e sujo por si só. É mais a parte de copiar e colar que é um pouco desaprovada e como dependemos do histórico de comandos para salvá-lo para nós.
@sitaram: seu um forro tem realmente un-onelinerish características: linha shebang, nova linha, quatro chamadas de serviços públicos - dois deles sed "programas". Eu acho que o script perl original parecia melhor, rodava mais rápido e não desperdiçava bytes, espalhando-se em 60 linhas. E o perl também permite que você aperte um pouco.
Para mim, esse é exatamente o tipo de linha a evitar. Você gostaria de ter isso (colado) na sua linha de comando? Não, e se você armazená-lo em um arquivo de qualquer maneira (não importa script ou função), poderá investir dois ou três novos bytes de linha para fazer com que pareça agradável.
10 min. mais tarde: eu só queria verificar se posso dizer "dois programas sed" ou se trata de "duas substituições / chamadas sed". Mas a resposta do sitaram se foi. Minha resposta ainda faz sentido, espero.
fonte