bash linha de comando - como converter várias linhas em uma única linha para sh -c

1

Na linha de comando do OSX, tenho alguma lógica como segue.

for i in {1..10}
do
   for j in {1..10}
   do
       echo "test inner"
   done;
   echo "test outer"
done

Funciona bem. Mas quero executá-lo a partir de nohup . Então eu preciso combinar acima em uma única linha para caber em nohup sh -c "{a single line}"

No entanto, a linha a seguir dá erro. Ele simplesmente pulou toda a quebra de linha de cima.

sh -c 'for i in {1..10} do for j in {1..10} do echo "test inner" done; echo "test outer" done'

Erro:

sh: -c: line 0: syntax error near unexpected token 'echo'
sh: -c: line 0: 'for i in {1..10} do for j in {1..10} do echo "test inner" done; echo "test outer" done'

Editar:

Eu não queria executá-lo como um arquivo, pois o comando tem credenciais ligeiramente protegidas. A maneira mais fácil de pensar é executá-lo como um comando para que não deixe um arquivo na VM compartilhada. Eu não sei o quão bem isso protege as credenciais ou há uma maneira melhor. Mais sugestões / idéias são bem vindas.

Editar:

Usar o bash e aspas simples faz com que funcione. (com base na resposta de Tigrão)

bash -c 'for i in {1..10}; do for j in {1..10}; do echo "test inner"; done; echo "test outer"; done;'

    
por Weishi Zeng 27.08.2017 / 08:43

3 respostas

3

A maneira que eu vejo é que você tem duas opções:

  1. Coloque isso em um arquivo de script e execute THAT
  2. Substitua cada nova linha na janela de código maior acima por um ponto e vírgula

Eu iria com 1, pessoalmente.

    
por 27.08.2017 / 08:47
3

Não há problema em ter caracteres de nova linha no argumento para sh -c . A sintaxe {1..10} é zsh (agora suportada por alguns outros shells), não sh . Se o seu sh resultar em algo diferente de {1..20} upon echo {1..20} , então é uma violação de conformidade POSIX e você deve estar pronto para ser corrigido em versões mais recentes. Você pode usar:

zsh -c '
  for i in {1..10}
  do
     for j in {1..10}
     do
         echo "test inner"
     done
     echo "test outer"
  done'

Ou

sh -c '
   i=1; while [ "$i" -le 10 ]
   do
     j=1; while [ "$j" -le 10 ]
     do
       echo "test inner"
       j=$((j + 1))
     done
     echo "test outer"
     i=$((i + 1))
  done'

Mas parece bobagem executar 100% de comandosecho para isso enquanto você pode fazer isso com apenas um comando:

awk 'BEGIN{
  for (i=1; i<=10; i++) {
    for (j=1; j<=10; j++)
      print "test inner"
    print "test outer"
  }}'

Que você pode colocar em uma única linha se quiser com:

awk 'BEGIN{for(i=1;i<=10;i++){for(j=1;j<=10;j++)print"test inner";print"test outer"}}'
    
por 27.08.2017 / 13:19
2

Para converter isso em uma única linha. Eu adicionei alguns ; nos locais corretos:

for i in {1..10}; do for j in {1..10}; do echo "test inner ${j}"; done; echo "test outer ${i}"; done;

A linha acima funcionará com bash , mas para executar isso com sh -c você precisa expandir o {1..10} (até onde eu sei) porque sh não suporta essa sintaxe de intervalo. Nesse caso, a seguinte linha funciona para mim:

sh -c 'for i in 1 2 3 4 5 6 7 8 9 10; do for j in 1 2 3 4 5 6 7 8 9 10; do echo "test inner ${j}"; done; echo "test outer ${i}"; done;'

Observação: eu adicionei ${j} e ${i} para confirmar.

    
por 27.08.2017 / 10:50