Qual seria realmente o objetivo de conseguir isso? Por que isso pode ser interessante / relevante?
vanádio
25
@vanadium somos usuários de Linux, tentando coisas inúteis nos permite aprender técnicas que podem ser aplicadas mais tarde para coisas mais complexas, se nenhum de nós nunca fez nenhum ser honesto que nos deixa de nós estaria aqui
Darren H
1
@DarrenH Isso é o que eu pensei na verdade :-)
vanádio
Respostas:
19
A maneira simples (e mais eficiente) é via loop for (em uma linha, mas aqui é mostrada em várias linhas para maior clareza):
for i in{date,grade};do
apt up${i}done
A maneira inteligente é criar um alias ~/.bashrcpara esses dois comandos e esquecer de digitá-lo novamente:
alias upgrade=' sudo apt update && sudo apt upgrade'
Veja o que está acontecendo? Estamos construindo uma sequência de texto válida para ser executada pelo shell. Agora tudo que você precisa fazer é usar em evalvez de echo. Mas evalgeralmente não é recomendado em scripts de shell e esse comando é muito mais complicado e não portátil do que o loop for. Variação sobre o tema sem eval (e mais curto até agora, mas não é eficiente devido à tubulação e comandos múltiplas echo, dois apt, sudoe shassim que os lotes de bifurcação):
$ echo "apt "{update,upgrade}";"|sudo sh
Também podemos usar setpara transformar a sequência desejada em parâmetros posicionais e apenas executar aptcom $1e $2args:
Ou use alternativamente o loop for novamente, pois o padrão é o processamento de parâmetros posicionais se você não especificar uma sequência no for variable (sequence)
O uso seté uma técnica muito comum que eu vejo entre profissionais que trabalham muito com conchas, e por uma boa razão - é muito portátil e funcionará /bin/shonde você não tem matrizes ou {a,b,c}expansão. Maneira POSIX-ly portátil seria set update upgrade ; for i; do echo apt $i ;done. Além disso, isso deve ser eficiente.
Basta fazer o loop for em uma linha. for i in {date,grade}; do sudo apt up${i}; done
Videonauth 22/10/19
3
Se você prefere manter seus arquivos em ordem, também pode colocar aliases ~/.bash_aliases. Este arquivo deve ser gerado automaticamente por ~/.bashrc.
francescop21
2
Atualizei minha resposta com talvez o que você deseja. É uma frase única, mas acho que não facilita. Francamente, não faz sentido fazer isso quando você deseja executar dois comandos (sim, são dois aptcomandos) com argumentos diferentes (atualização e atualização), então ainda direi que o loop é o caminho a seguir
Sergiy Kolodyazhnyy
1
Não há necessidade de expansão de string no cabeçalho de loop, apenas nomeie as iterações:for i in date grade; do
rexkogitans
5
Obviamente, esse apelido deve ser nomeado upgrate.
pipe
14
Você também pode usar a expansão do histórico do bash para obter partes da linha de comando atual e modificá-la:
Então você pode correr repeat 'apt up' {date,grade}. Isso tem o benefício de ser reutilizável para comandos totalmente diferentes, embora não esteja poupando a digitação deste.
Eu certamente concordaria com algumas das outras respostas de que algo como isso é provavelmente mais útil:
Respostas:
A maneira simples (e mais eficiente) é via loop for (em uma linha, mas aqui é mostrada em várias linhas para maior clareza):
A maneira inteligente é criar um alias
~/.bashrc
para esses dois comandos e esquecer de digitá-lo novamente:A maneira elaborada é fazer isso:
Veja o que está acontecendo? Estamos construindo uma sequência de texto válida para ser executada pelo shell. Agora tudo que você precisa fazer é usar em
eval
vez deecho
. Maseval
geralmente não é recomendado em scripts de shell e esse comando é muito mais complicado e não portátil do que o loop for. Variação sobre o tema sem eval (e mais curto até agora, mas não é eficiente devido à tubulação e comandos múltiplasecho
, doisapt
,sudo
esh
assim que os lotes de bifurcação):Também podemos usar
set
para transformar a sequência desejada em parâmetros posicionais e apenas executarapt
com$1
e$2
args:Ou use alternativamente o loop for novamente, pois o padrão é o processamento de parâmetros posicionais se você não especificar uma sequência no
for variable (sequence)
O uso
set
é uma técnica muito comum que eu vejo entre profissionais que trabalham muito com conchas, e por uma boa razão - é muito portátil e funcionará/bin/sh
onde você não tem matrizes ou{a,b,c}
expansão. Maneira POSIX-ly portátil seriaset update upgrade ; for i; do echo apt $i ;done
. Além disso, isso deve ser eficiente.Ou podemos seguir a
while
rota do loop:É claro que lembre-se de executá-lo sem
echo
que a execução real do comando ocorrafonte
for i in {date,grade}; do sudo apt up${i}; done
~/.bash_aliases
. Este arquivo deve ser gerado automaticamente por~/.bashrc
.apt
comandos) com argumentos diferentes (atualização e atualização), então ainda direi que o loop é o caminho a seguirfor i in date grade; do
upgrate
.Você também pode usar a expansão do histórico do bash para obter partes da linha de comando atual e modificá-la:
!#
é a linha atual:s/date/grade
é um modificador que substituidate
porgrade
fonte
!#:s/dat/grad
vez dissoOutra opção simples usando, em
xargs
vez defor
:Teste:
No entanto, eu preferiria um apelido de shell como Sergiy, porque essas maneiras "simples" não são simples o suficiente para serem realmente úteis.
fonte
printf "%s\n" {date,grade} | xargs -I% -n1 echo apt up%
embora isso seja um pouco mais longoprintf '%s'
geralmente é uma boa prática, pois você não pode escapar dela, por exemplo, com--help
ou-e
.printf '%s\0'
seria ainda melhor,xargs
tem uma bandeira para lidar com argumentos terminados nulos #Crie uma função como esta:
Então você pode correr
repeat 'apt up' {date,grade}
. Isso tem o benefício de ser reutilizável para comandos totalmente diferentes, embora não esteja poupando a digitação deste.Eu certamente concordaria com algumas das outras respostas de que algo como isso é provavelmente mais útil:
fonte
A resposta de @ muru me levou a ler sobre a expansão do histórico e encontrei outra variante
^string1^string2^
é equivalente a!!:s/string1/string2/
, que pega o último comando e substituistring1
porstring2
.fonte
Eu reuso a
apt-get up
parte do comando usando a seguinte sequência de teclas:Up ArrowBackspaceBackspaceBackspaceBackspace
fonte