AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 700675
Accepted
Dominick Pastore
Dominick Pastore
Asked: 2022-04-28 20:52:50 +0800 CST2022-04-28 20:52:50 +0800 CST 2022-04-28 20:52:50 +0800 CST

Por que echo -e está se comportando de maneira estranha em um Makefile?

  • 772

Eu estava escrevendo um Makefile (no Ubuntu 20.04, se for relevante) e notei um comportamento interessante com o echo. Pegue este Makefile simples:

test.txt:
        @echo -e 'hello\nworld'
        @echo -e 'hello\nworld' > test.txt

Quando eu executo make, eu esperaria ver a mesma coisa no stdout que no test.txt, mas na verdade não vejo. Eu recebo isso no stdout:

hello
world

mas isso em test.txt:

-e hello
world

Enquanto isso, se eu remover -ede ambas as linhas no Makefile, recebo isso no stdout:

hello\nworld

e isso em test.txt:

hello
world

Isso me fez pensar se echodetecta o redirecionamento e se comporta de maneira diferente, mas não quando eu apenas o executo manualmente no shell /bin/echo -e 'hello\nworld' > test.txt(que produz helloe worldem linhas separadas, como eu normalmente esperaria). Cheguei até a confirmar que o Makefile está usando /bin/echo em vez de um shell embutido adicionando uma @echo --versionlinha.

O que está acontecendo aqui?

echo gnu-make
  • 1 1 respostas
  • 2323 Views

1 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2022-04-28T21:29:04+08:002022-04-28T21:29:04+08:00

    Implementações compatíveis com UNIX echosão necessárias para saída -e<space>hello<newline>world<newline>lá.

    Aqueles que não são compatíveis. Muitos não são, o que significa que é quase impossível usar echoportátil, printfdeve ser usado em vez disso . bash's echo, em algumas (a maioria) compilações dele, só é compatível quando você habilita as opções posixe xpg_echo. Esse pode ser o echocomportamento que você estava esperando.

    O mesmo para o echoutilitário autônomo que vem com o GNU coreutils, que só é compatível se for invocado com $POSIXLY_CORRECTset em seu ambiente (e for de uma versão recente o suficiente).

    makenormalmente é executado shpara interpretar as linhas de comando em cada linha de ação.

    No entanto, a implementação GNU de make, como uma otimização, pode executar comandos diretamente se o código for simples o suficiente e achar que não precisa invocar um shell para interpretá-lo.

    Isso explica porque echo --versionte dá /bin/echo, mas echo ... > fileprecisa de um shell para realizar o redirecionamento.

    Você pode usar strace -fe execve makepara ver o que makeé executado (ou o truss/ tusc... equivalente em seu sistema se não for Linux).

    Aqui, parece que, embora o seu /bin/echonão seja compatível, o seu shpossui um echobuilt-in compatível.

    Aqui, use printfse você quiser expandir echoas sequências de escape -style:

    printf '%b\n' 'hello\nworld'
    

    Em seu argumento de formatoprintf , entende as sequências de escape do estilo C (há uma diferença com as do estilo echo para as sequências octais \0xxx(eco) vs (C))\xxx

    printf 'hello\nworld\n'
    

    Aqui, você também pode fazer:

    printf '%s\n' hello world
    

    Qual é a maneira comum e portátil de gerar vários argumentos em linhas separadas.

    Outra abordagem seria adicionar:

    SHELL = bash
    

    Para o seu Makefilefor makeinvocar bash(supondo que esteja instalado e encontrado em $PATH) em vez de shinterpretar as linhas de comando. Ou invoque makecomo make <target> SHELL=bash.

    Isso não o tornará necessariamente mais portátil, pois, embora haja cada vez mais sistemas bashinstalados por padrão nos dias de hoje, há alguns (como no Solaris) em que bashé construído para que seu echointerno se comporte da maneira padrão por padrão.

    Definir SHELLpara algo diferente de /bin/shtambém tem o efeito colateral de desabilitar makea otimização do GNU mencionada acima, portanto, com make <target> SHELL=shoumake <target> SHELL=/bin//sh , você obteria comportamentos consistentes entre as duas invocações, sem precisar adicionar uma dependência ao bash.

    • 27

relate perguntas

  • Faça eco de algo para consolar sempre que sair do crontab

  • Por que `md5sum` não fornece o mesmo hash que a Internet?

  • ssmtp [email protected] < file.log não funciona. O corpo está em branco

  • Imprima uma mensagem um determinado número de vezes, logo após a inicialização do sistema (init) em um sistema sem GUI [duplicado]

  • Alguém pode explicar o comportamento estranho da barra invertida na substituição de comando?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve