Como adicionar novas linhas em variáveis ​​no script bash


Respostas:


73

Em bashvocê pode usar a sintaxe

str=$'Hello World\n===========\n'

Aspas simples precedidas por a $são uma nova sintaxe que permite inserir seqüências de escape em strings.

Também printfembutido permite salvar a saída resultante em uma variável

printf -v str 'Hello World\n===========\n'

Ambas as soluções não requerem um subshell.

Se você precisar imprimir a sequência a seguir, use aspas duplas, como no exemplo a seguir:

echo "$str"

porque quando você imprime a sequência sem aspas, a nova linha é convertida em espaços.


11
Como é str=$'Hello World\n===========\n'chamada a sintaxe ? substituição de variável?
Zengr 10/08/13

5
@zengr: É chamado de citação ANSI-C , e também é suportado em zshe ksh; no entanto, NÃO é compatível com POSIX.
precisa saber é o seguinte

4
@ mkelement0, vem de ksh93, também é suportado pelo zsh, festança, mksh e sh FreeBSD, e sua inclusão na próxima grande revisão do POSIX é em discussão
Stéphane Chazelas

11
Não parece funcionar com aspas duplas? por exemplo str=$"My $PET eats:\n$PET food"? Esta abordagem funciona para aspas duplas
Brad Parks

31

Você pode colocar novas linhas literais entre aspas simples (em qualquer shell no estilo Bourne / POSIX).

str='Hello World
===========
'

Para uma sequência de múltiplas linhas, aqui os documentos geralmente são convenientes. A cadeia é alimentada como entrada para um comando.

mycommand <<'EOF'
Hello World
===========
EOF

Se você deseja armazenar a sequência em uma variável, use o catcomando em uma substituição de comando. O (s) caractere (s) de nova linha no final da cadeia de caracteres será removido pela substituição do comando. Se você deseja manter as novas linhas finais, coloque uma tampa no final e retire-a depois. Em shells compatíveis com POSIX, você pode escrever str=$(cat <<'EOF'); str=${str%a}seguido pelo heredoc propriamente dito, mas o bash exige que o heredoc apareça antes do parêntese de fechamento.

str=$(cat <<'EOF'
Hello World
===========
a
EOF
); str=${str%a}

No ksh, bash e zsh, você pode usar o $'…'formulário entre aspas para expandir escapes de barra invertida dentro das aspas.

str=$'Hello World\n===========\n'

11
Estou usando o GNU bash 4.1.5 e str=$(cat <<'EOF')não funciona como está. As )necessidades devem ser colocadas na próxima linha após o final do documento EOF.. mas, mesmo assim, ele perde a nova linha à direita devido ao comando Substituição.
precisa saber é o seguinte

@ fred Bons pontos, expliquei sobre as novas linhas à direita e mostrei o código que funciona no bash. Eu acho que é um bug no bash, embora, para ser honesto, ao reler a especificação POSIX, não seja claro que o comportamento seja obrigatório quando o << estiver dentro de uma substituição de comando e o heredoc não.
Gilles 'SO- stop be evil'

Coisas boas; para preservar as \ninstâncias finais (e principais) bashao capturar um documento aqui em uma variável, considere IFS= read -r -d '' str <<'EOF'...como uma alternativa à abordagem de interrupção (veja minha resposta).
precisa saber é o seguinte

8

Você está usando "eco"? Tente "eco-e".

echo -e "Hello World\n===========\n"

2
Entre. Você não precisa do final \ n, porque echoele adicionará automaticamente um, a menos que você especifique -n. (No entanto, o principal problema da questão é como obter essas novas linhas em uma variável).
precisa saber é o seguinte

+1 De todas as soluções, esta é a mais direta e mais simples.
Hai Vu

echo -e não funciona no OS X
Greg M. Krsak 04/04

2
@GregKrsak: In bash, echo -e faz o trabalho no OS X - que é porque echoé uma festa builtin (em vez de um executável externo) e que builtin suporta -e. (Como um builtin, ele deve funcionar em todas as plataformas que o bash é executado em, aliás, echo -etrabalha em kshe zshtambém). Por outro lado, no entanto, o utilitário externoecho no OS X - /bin/echo- na verdade não suporta -e.
usar o seguinte comando

4

Se você precisar de novas linhas em seu script muitas vezes, poderá declarar uma variável global que contém uma nova linha. Dessa forma, você pode usá-lo em cadeias de citação dupla (expansões variáveis).

NL=$'\n'
str="Hello World${NL} and here is a variable $PATH ===========${NL}"

Por que $''exigiria um subshell?
Mat

Desculpe, eu li mal uma resposta.
pihentagy

Eu poderia pedir explicações aos que recusaram?
precisa saber é o seguinte

Agradável! Isso pode ser incluído em variáveis ​​usando aspas duplas, por exemplo"My dog eats:${NL}dog food"
Brad Parks

Isso funcionou para mim. Ao usar um script bash para compor uma sequência que é automaticamente copiada na área de transferência para colar posteriormente em outro lugar, essa abordagem funcionou para adicionar novas linhas na saída resultante.
Ville

3

De todas as discussões, aqui está a maneira mais simples para mim:

bash$ str="Hello World
==========="
bash$ echo "$str"
Hello World
===========

O comando echo deve usar aspas duplas .


3

Para complementar as ótimas respostas existentes:

Se você estiver usando bashe preferir usar novas linhas reais para facilitar a leitura , readé outra opção para capturar um documento aqui em uma variável , que (como outras soluções aqui) não requer o uso de um subshell.

# Reads a here-doc, trimming leading and trailing whitespace.
# Use `IFS= read ...` to preserve it (the trailing \n, here).
read -r -d '' str <<'EOF'   # Use `IFS= read ...` to preserve the trailing \n
Hello World
===========
EOF
# Test: output the variable enclosed in "[...]", to show the value's boundaries.
$ echo "$str"
[Hello World
===========]
  • -rgarante que readnão interprete a entrada (por padrão, trataria barras invertidas especiais, mas isso raramente é necessário).

  • -d ''define o delimitador "record" como uma string vazia, fazendo readcom que leia toda a entrada de uma só vez (em vez de apenas uma única linha).

Observe que, deixando $IFS(o separador de campo interno) em seu padrão $' \t\n'(um espaço, uma guia, uma nova linha), qualquer espaço em branco à esquerda e à direita é aparado a partir do valor atribuído a $str, que inclui a nova linha à direita do documento.
(Observe que, embora o corpo do documento aqui inicie na linha após o delimitador de início ( 'EOF'aqui), ele não contém uma nova linha principal ).

Geralmente, esse é o comportamento desejado, mas se você deseja essa nova linha à direita, use em IFS= read -r -d ''vez de apenas read -r -d '', mas observe que qualquer espaço em branco à esquerda e à direita é preservado.
(Observe que anexar IFS= diretamente ao readcomando significa que a atribuição está em vigor apenas durante esse comando, portanto, não há necessidade de restaurar o valor anterior.)


O uso de um documento aqui também permite que você use opcionalmente o recuo para ativar a cadeia de linhas múltiplas para facilitar a leitura:

# Caveat: indentation must be actual *tab* characters - spaces won't work.
read -r -d '' str <<-'EOF' # NOTE: Only works if the indentation uses actual tab (\t) chars.
    Hello World
    ===========
EOF
# Output the variable enclosed in "[...]", to show the value's boundaries.
# Note how the leading tabs were stripped.
$ echo "$str"
[Hello World
===========]

A colocação -entre <<e o delimitador here-doc de abertura ( 'EOF', aqui) faz com que os caracteres de tabulação iniciais sejam retirados do corpo do doc here e até do delimitador de fechamento, mas observe que isso só funciona com caracteres de tabulação reais , não espaços, por isso, se você editor converte pressionamentos de tecla da guia em espaços, é necessário trabalho extra.


-1

você precisa fazer assim:

STR=$(echo -ne "Hello World\n===========\n")

Atualizar:

Como Fred apontou, dessa maneira você perderá o "\ n" final. Para atribuir variáveis ​​com as seqüências de barra invertida expandidas, faça:

STR=$'Hello World\n===========\n\n'

vamos testá-lo:

echo "[[$STR]]"

nos dá agora:

[[Hello World
===========

]]

Observe que $ '' é diferente de $ "". O segundo faz a tradução de acordo com a localidade atual. Para oital, consulte a seção CITAÇÕES em man bash.


-2
#!/bin/bash

result=""

foo="FOO"
bar="BAR"

result+=$(printf '%s' "$foo")$'\n'
result+=$(printf '%s' "$bar")$'\n'

echo "$result"
printf '%s' "$result"

resultado:

FOO
BAR

FOO
BAR

11
Por que não simplesmente result+=$foo$'\n'? $(printf %s "$foo")apararia os caracteres de nova linha à direita, $foose houver.
Stéphane Chazelas 26/09/16

Não há explicação para o código; caso contrário, parece bom para mim.
somethingSomething
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.