O que pode explicar os exemplos abaixo e como faço para corrigir isso, de preferência sem citar acrobacias pesadas? Estou usando o $n
para simular várias sequências de comandos de linha, apenas no caso de distrair você da questão real.
~$ n=$'\n'; sudo -i echo "line1${n}line2${n}"
line1line2
~$
mas
~$ n=$'\n'; sudo echo "line1${n}line2${n}"
line1
line2
~$
A execução
sudo -i echo $'line1\nline2'
sob strace mostra que o Bash começa assim:Agora,
strace
apresenta caracteres especiais com escapes de barra invertida quando exibe as strings, então o que o Bash realmente obtém como argumento-c
é e para o shell, uma barra invertida no final de uma linha marca uma linha de continuação e remove a barra invertida e a seguinte nova linha .echo line1[backslash][newline]line2[backslash][newline]
Sem
-i
,sudo
executaecho
diretamente, sem passar pelo shell:Aqui, é uma nova linha literal indo para
echo
, eecho
imprime isso devidamente.A ideia aqui deve ser que
sudo
tenta adicionar uma camada de shell escapando para acomodar o fato de quesh -c
leva uma única string, enquantosudo
ele próprio leva o comando como argumentos distintos.Compare os seguintes casos:
sudo
escapa do espaço (este é apenas o nome do comando, sem argumentos!):sudo
escapa da barra invertida, para que isso realmente funcione (o Bashecho
não processa a barra invertida):O mesmo com uma guia:
Aqui, não há aspas extras na barra invertida, então o Bash a remove enquanto processa a linha de comando do shell (
b
não é um caractere especial para o shell e não precisa de aspas. Isso é basicamente o mesmo quebash -c 'echo foo"b"ar'
):O problema é que você não pode escapar de uma nova linha com uma barra invertida e
sudo
não parece levar isso em consideração.De qualquer forma, citar problemas como esse provavelmente ficará um pouco mais fácil se você armazenar os comandos que deseja em um arquivo e executá-lo como um script.
Você pode alterar a estrutura do comando:
Desta forma
sudo
, não vê o argumento e, portanto, não pode estragá-lo.