erro Heredocument que não consigo entender (“delimitado pelo final do arquivo”)

3

Eu executo o seguinte código no Bash:

bash /dev/fd/10 10<<-'SES'

    cat <<EMR >> /etc/apache2/apache2.conf
        #
        <Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
        </Directory>
        EMR

SES

Mas a execução quebra e eu fico:

warning: here-document at line 2 delimited by end-of-file (wanted 'EMR')

  • Eu não entendo o que o erro significa e já adicionei - entre o operador e o nome do heredoc contido para permitir tabulações.
  • Eu me certifiquei de que não houvesse espaços após o abridor (operador + nome) ou após o delimitador .

Observação: se você copiar o código acima para testá-lo em seu computador, precisará alterar todos os espaços iniciais para tabulações (tabulações), pois o StackExchange alterou as tabulações originais para espaços.

Possíveis causas a excluir:

Existem várias causas possíveis para isso, aqui estão algumas que descartei:

1. Caracteres ocultos problemáticos:

Eu edito o arquivo com o Notepad ++ e ligo o modo "Mostrar todos os símbolos" para garantir que todos os recuos sejam baseados em tabulação (veja setas vermelhas) e que todos os caracteres de fim de linha (EOLs) sejam LF unix ( não há CR chars):

Alémdisso,acodificaçãoéUTF-8,portanto,nãoéumproblemadecodificação.

2.Símbolodepseudo-traço(<<-):

Parecequeohífenadicionado(<<-)nãofazotrabalhoderemovertodasasguiasprincipaisporque,quandoexcluomanualmentetodasasguiasprincipaisqualquer(outodasasguiasprincipaisantescadadelimitador)oheredocfuncionacomoesperado.Pode-sesugerirqueohífennãoérealmenteumsímbolotraço,masporquenãoserá?Nãotenhocomovalidarisso.

3.Errodebash:

OutraspessoasquenãousamoWindowseusamdiferentesdistrosLinuxcontendoBashnãotêmisso,entãoébemprovávelqueissonãosejaumerrodeBash.EutambémtesteiissocomaseçãodedesenvolvimentodoBashnoGNU.

ColocaçãocorrompidadedadoscopiadosdoNotepad++podeser:

SeeucolaroheredocdoNotepad++emumarquivonano,parecequeasguiasprincipaisestãotodasnolugar-elasnãosãoexcluídassãotransformadasemespaçosnacolagem.

Alémdisso,catscript.sh|grep"^ " e cat script.sh | grep -x '\s*EMR' (quando feitos no diretório de arquivos), saem vazios.

No entanto, em uma colação posterior, encontrei outro problema de corrupção que é mais provável causar isso (veja minha resposta).

    
por JohnDoea 19.04.2017 / 12:37

3 respostas

2

O problema, sem dúvida, se origina no Windows. Ele lida com o tamanho da janela TTY; Quanto mais estreito for o tamanho da janela, mais caracteres de alimentação de linha ( LF ) e retorno de carro ( CR ) char combos serão adicionados na colagem pela estreiteza da janela. Esses combos são representados como CRLF .

Solução

Se eu entendi o mantenedor do Nano Benno Schulenberg correto, o Nano irá naturalmente converter CRLF combos em caracteres Trailing Whitespace ( ^J chars).

Como sugerido por Benno, adicionar o seguinte código no final de /etc/nanorc resolveu:

bind ^J enter main

Clarificando a solução

Por um lado, ele desabilitará a formação de ^J chars que quebram o código; por outro lado, ele adicionará somente Line Feeds ( LF chars), aplicável no Linux (ao contrário do Windows CRLF combos), aos dados copiados.

Os caracteres LF unicamente adicionados são bons, pois evitam que os dados colados apareçam como uma longa linha de texto.

por 24.04.2017 / 23:54
8

A imagem que você postou mostra retornos de carro ( CR na imagem). Este é um arquivo de texto formatado em DOS. Use dos2unix ou algum utilitário semelhante para converter o arquivo em um arquivo de texto Unix apropriado.

Como comentário abaixo: Se você realmente precisa fazer desenvolvimento no Notepad ++ no Windows (eu pessoalmente recomendaria fazer o desenvolvimento no mesmo sistema operacional que você está alvejando, se possível), então o programa pode ser solicitado a salvar arquivos de texto com novas linhas do Unix selecionando "Unix (LF)" nas preferências "Novos Documentos":

Certifique-sedequeseuarquivotenhaumanovalinha(LF)nofinaldaúltimalinha.TodaslinhasemumarquivodetextoUnix(eumscriptdeshelléumarquivodetexto)precisadeumanovalinhanofinal.Seaúltimalinhanãotiveruma,oarquivotecnicamentenãoéumarquivodetexto,massimumarquivobinário.

Vejatambém,porexemplo,asrespostaspara" Remover o caractere ^ M do arquivos de log "

    
por 19.04.2017 / 20:04
7

Infelizmente, o design dos emuladores de terminal (como a janela do terminal na sua caixa do Ubuntu) não permite um bom suporte à colagem; em particular, na maioria das vezes, colar funciona exatamente como digitar a mesma coisa (se você fosse um digitador rápido muito). A maioria das coisas que você acha que é um sinal especial para o programa em execução no terminal é, na verdade, dados em banda - isto é, apenas um caractere. Se a sua pasta contiver esse caractere, o programa não poderá dizer a diferença entre você digitar o caractere e colá-lo.

Assim, você não pode realmente usar colar para transferir arquivos, a menos que não contenham caracteres que possam confundir o programa de recebimento. Em particular, as guias que sua pasta contém são confusas - ele está vendo uma tabulação e tentando executar o arquivo ou o comando. Assim como quando você digita uma guia.

O truque cat > filename pode falhar se houver um controle D (sim, esse é um caractere) no conteúdo colado. Mas se você evitar caracteres de controle (além de nova linha e tabulação), isso deve funcionar.

As pessoas do Unix normalmente usam programas de transferência de arquivos para mover arquivos. O básico que usamos principalmente é scp ou sftp , ambos fazem parte do SSH (e, portanto, são totalmente criptografados, autenticados, etc. - as mesmas garantias de segurança que o SSH fornece).

A maneira mais fácil de trabalhar entre o Windows e uma VM do Ubuntu (ou vice-versa) é provavelmente usar os recursos de compartilhamento de arquivos do seu hipervisor (produto do VM) - a maioria deles. Você pode escolher um diretório no host e ele ficará visível dentro do convidado. Com o WSL, você pode acessar todos os seus arquivos do Windows em /mnt/<drive letter>/ . Se o seu hipervisor não tiver esse recurso, o segundo mais fácil é usar um compartilhamento de arquivo comum. Você pode montar compartilhamentos de arquivos do Windows a partir do Ubuntu ou instalar o Samba no Ubuntu para fazer compartilhamentos de arquivos para o Windows.

Dependendo do que você está fazendo, pode haver melhores abordagens. Por exemplo, implantação automatizada. Talvez você queira tê-lo algum que você verifique o arquivo para git, e então ele é automaticamente implantado na sua caixa Ubuntu quando você faz um git push ? Isso pode ser tão simples quanto usar git hooks, ou muito mais complicado - existem pacotes inteiros de software dedicados a ele.

Finalmente, há uma grande vantagem em escrever esses scripts em arquivos, não apenas colá-los em um shell: o arquivo serve como documentação do que você fez. Algo deu errado? A menos que seja realmente errado, verifique o arquivo para ver o motivo. Isso permite determinar exatamente o que deu errado, geralmente o primeiro passo para reparar o dano. Precisa fazer de novo? Apenas forneça o arquivo pela segunda vez. Precisa fazer algo parecido? Edite o arquivo e, em seguida, digite-o.

Se você precisar colar um aqui-doc:

Se você quiser colar diretamente no bash, a melhor opção é garantir que ele não contenha caracteres de controle que não sejam newline. Colando isso deve funcionar:

bash /dev/fd/10 10<<'SES'

cat <<EMR >> /etc/apache2/apache2.conf
#
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
EMR

SES

Se você precisa ter o recuo, pode usar espaços e sed ao invés do primeiro - para removê-lo (observe aqui que foi em frente e usou stdin em vez de fd 10 porque a sintaxe é mais fácil e duvido que seja importante) :

sed -e 's/^\s\+//' <<'SES' | bash

    cat <<EMR >> /etc/apache2/apache2.conf
    #
    <Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
    </Directory>
    EMR

SES

Que usa a funcionalidade de substituição de pesquisa do sed ( s/PATTERN/REPLACEMENT/ ) para olhar o início da linha ( ^ ) para espaço em branco ( \s ) repetido uma ou mais vezes ( \+ ) e substitui por nada . Em outras palavras, corta todos os espaços principais em cada linha. A opção -e para sed identifica explicitamente que isto é um script sed para ser executado - não é realmente necessário, sed irá interpretar seu primeiro argumento como script de qualquer maneira - mas eu pessoalmente acho mais claro usar sempre -e .

Observe que "espaço em branco" acima inclui espaços e tabulações (e mais alguns caracteres que não são realmente relevantes aqui). Esse sed irá cortar todos eles, independentemente da mixagem usada.

Claro, eu não tenho idéia do porque você está colando um comando no bash dizendo para ele executar o bash para rodar o cat.

    
por 21.04.2017 / 18:35