Estou tentando armazenar várias linhas em uma variável bash, mas parece não funcionar.
Por exemplo, se eu listar /bin
um arquivo por linha e armazená-lo $LS
, passo $LS
como stdin para wc
, ele sempre retornará 1:
$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1
Se eu tentar imprimir na tela, obtenho vários resultados: echo
imprime todas as linhas em uma única linha, enquanto printf
imprime apenas a primeira linha:
#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS
Então, uma variável bash pode conter várias linhas?
printf "%s\n" $LS
faria.wc
e com outros comandos:wc -l <<< "$LS"
printf '%s\n' "$LS"
se você quiser ver uma nova linha. Isso é digitação incorreta, consertou!As novas linhas estão na variável
LS=$(ls -1)
define a variávelLS
para a saída dels -1
(que produz a mesma saída quels
, a propósito, exceto quando a saída vai para um terminal), menos novas linhas finais.O problema é que você está removendo as novas linhas quando imprime o valor. Em um script de shell,
$LS
não significa "o valor da variávelLS
", significa "tome o valor deLS
, divida-o em palavras de acordo comIFS
e interprete cada palavra como um padrão global”. Para obter o valor deLS
, você precisa escrever"$LS"
, ou mais geralmente, colocar$LS
entre aspas duplas.echo "$LS"
imprime o valor deLS
, exceto em algumas conchas que interpretam caracteres de barra invertida e, exceto por alguns valores que começam com-
.printf "$LS"
imprime o valor deLS
desde que não contenha nenhum caractere de porcentagem ou barra invertida e (com a maioria das implementações) não começa-
.Para imprimir o valor de
LS
exatamente , useprintf %s "$LS"
. Se você deseja uma nova linha no final, useprintf '%s\n' "$LS"
.Observe que
$(ls)
geralmente não é a lista de arquivos no diretório atual. Isso funciona apenas quando você tem nomes de arquivos domados o suficiente. Para obter a lista de nomes de arquivos (exceto arquivos de ponto), você precisa usar um curinga:*
. O resultado é uma lista de cadeias, não uma cadeia, portanto, você não pode atribuí-la a uma variável de cadeia; você pode usar uma variável de matrizfiles=(*)
em shells que os suportam (ksh93, bash, zsh).Para obter mais informações, consulte Por que meu script de shell é bloqueado em espaço em branco ou em outros caracteres especiais?
fonte
O mencionado acima
é a única solução correta.
Deixe-me demonstrar que as outras soluções propostas, com
echo
eprintf
, simplesmente não funcionam corretamente:(Também é possível testar com
V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"
e variações.)Enquanto
\n
os nomes dos arquivos podem não ser tão comuns, armazene-osgit diff
em uma variável e suas chances de encontrar literal\n
aumentam drasticamente.fonte
ksh
ezsh
também suportaprint -r -- "$LS"
ezsh
também possuiecho -E - $LS
.csh
noecho $LS:q
entanto, isso não gera o caractere de nova linha se $ LS estiver vazio, e obter um valor de múltiplas linhas em $ LS em primeiro lugar é bastante complicado no csh.