Este código funciona bem no Linux, mas não no Mac OS:
#!/usr/bin/env bash
foo=$(cat <<EOF
"\[^"\]+"
EOF
)
printf "%s" "$foo"
Ele falha no Mac com
./test.sh: line 6: unexpected EOF while looking for matching `"'
./test.sh: line 7: syntax error: unexpected end of file
Se eu fizer isso cat <<EOF
em vez de foo=$(cat <<EOF
, funciona bem. Existe uma maneira portátil de obter heredocs (ou strings multiline) em variáveis sem usar um arquivo como intermediário?
Editar : Quero usar um heredoc porque tenho uma string multilinha com "
and '
. Meu exemplo real se parece com:
EXPECTED_ERROR=$(cat <<EOF
Set
: Type
File "/tmp/tmp[A-Za-z0-9_/]\+\.v", line 1\(0\|1\), characters 0-15:
Error: The command has not failed\s\?!
.\?Does this output display the correct error? \[(y)es/(n)o\]\s
I think the error is 'Error: The command has not failed\s\?!
.\?'\.
The corresponding regular expression is 'File "\[^"\]+", line (\[0-9\]+), characters \[0-9-\]+:\\\\n(Error:\\\\s+The\\\\s+command\\\\s+has\\\\s+not\\\\s+failed.*
EOF
)
Esse bug específico do bash foi corrigido no 4.0, lançado há mais de 15 anos, mas o macOS ainda fornece uma versão 3.2.x. Como a Apple aparentemente não atualizará seu
bash
(e seush
que AFAIK ainda é baseado embash
), eu sugiro que você relate o bug a eles para que eles façam backport de uma correção para sua versão.Parece que isso afeta os here-documents usados dentro da substituição de comando, então você pode mover o here-doc para fora da substituição de comando com:
ou usando uma função auxiliar:
Ou uma mais útil:
(acima também usando
'EOF'
instead of,EOF
pois o último faz expansões e implica em tratamento extra de barra invertida).Ou adie a interpretação do here-doc usando
eval
:Embora eu suspeite que você esteja usando here-docs em primeiro lugar para evitar ter que se preocupar com aninhamento de citações, isso
eval '...'
provavelmente não ajudará.Uma nota sobre terminologia:
Aqui, o problema é apenas sobre a versão do bash. Você encontraria o mesmo bug em qualquer sistema anterior a 2009 que tivesse o bash incluído.
Não está claro para mim por que você precisa de um heredoc:
deve funcionar no bash no Linux e no macOS.
Se você quiser uma string com várias linhas, declare-a entre aspas em várias linhas:
Fornecendo isso como uma resposta aqui para fornecer completude, já que todas as respostas contêm as respostas corretas. Isso apenas adiciona outra opção "correta" para o OP.
Um pouco de história
Darwin , baseado no BSD, e o núcleo do MacOS era livre e OpenSource até o Darwin8. O Darwin8 ainda está disponível e lhe dará um OSX 10.4 muito básico. Não haverá GUI nessa instalação. Depois do Darwin8, a Apple escolheu tornar o SO de código fechado. É também este Darwin8 que contém a última versão GPL do BASH da Apple - 3.2.x, razão pela qual nenhum usuário verá uma versão nativa do Apple BASH superior a 3.2.x
A Apple usou os objetos gráficos do NeXTStep e do Darwin8 acima para formar a base de todos os OSX modernos desde 10.4 e o código-fonte permanece fechado com bits e partes compartilhadas no site do desenvolvedor da Apple . O Darwin, sem o Apple anexado, ainda pode ser usado e visto hoje em projetos como o PureDarwin . Observe que ainda não há uma GUI nativa do tipo NeXTStep aqui ou qualquer GUI nativa, mas o sistema executará desktops como o XFCE usando o MacPorts . O Homebrew, discutido abaixo, é um gerenciador de pacotes que é usado principalmente para substituir as versões Apple/Darwin de programas e bibliotecas com suas contrapartes Linux (sem remover as versões fornecidas pela Apple). O MacPorts funciona da mesma forma, mas contém não apenas binários Linux, mas também aplicativos gráficos.
A questão
Com o pequeno histórico fora do caminho, Multiple Sites centra-se no fato de que a Apple violaria a licença GPLv3 se o BASH fosse atualizado além da versão em Darwin8. Relatar o bug pode não adiantar, pois a correção precisaria ser retroportada para continuar evitando a violação. Se a correção foi incluída no BASH4 como a resposta de Stephane declarou, a Apple agora se colocou em um problema de catch-22/ovo e galinha. Para atualizar o BASH para uma versão maior que 3.2, todo o código-fonte (incluindo o código NeXTStep de código fechado) precisaria ser relançado, o que satisfaria a licença GPL. A Apple não quer que o público veja esse código. Veja Sarcasmo abaixo para minha opinião pessoal sobre o porquê.
A resposta principal no resultado da pesquisa vinculado anteriormente contém o seguinte:
Comprometido em fornecer o Zsh Shell é apenas uma maneira elegante de dizer que temos muitos advogados que nos dizem que violar a GPL seria ruim, então vamos encontrar uma substituição viável com uma licença que não seja GPLv3. O ZSH é essa substituição adequada.
Minha solução
Usuários do sistema Apple não se importam em simplesmente trocar os interpretadores de terminal, mas como usuário de ambos os sistemas (PC e Mac), descobri que instalar a versão Homebrew do BASH corrige a decisão de design escolhida pela Apple.
Fazer isso agora torna os scripts BASH compatíveis entre quase todas as distribuições Linux e um Mac e, se desejado, fornece aos usuários uma maneira de continuar usando um shell BASH ao qual estão acostumados.
Desvantagem
Se os usuários precisam de portabilidade (ir de um Mac para outro), e não de compatibilidade, a abordagem acima é desencorajada. No caso da portabilidade, temos 2 opções:
Uma abordagem sem substituição de comando que funciona nos bashes mais antigos que tenho (não chegando ao 3.2):