HPR4667: UNIX Curio #9 - printf — Insubornavel

HPR4667: UNIX Curio #9 - printf

Por Vance23/06/2026 às 00:0033 visualizações
Foto: CC BY-SA / Hacker Public Radio
🎙 Vance · Hacker Public Radio

Este programa foi marcado como "Limpo" pelo anfitrião.

Esta série é dedicada a explorar itens pouco conhecidos — e ocasionalmente úteis — escondidos nos cantos poentes dos sistemas operacionais semelhantes ao UNIX.

O comando...... `echo`é muito útil; ele imprime os argumentos fornecidos a ele, seguidos por um caractere de nova linha. (A nova linha também é chamada, às vezes, de "feed de linha", dependendo de quem está escrevendo ou falando, e tem o valor decimal ASCII 10.) Ele tem muitas aplicações, seja em um script ou interativamente na linha de comando.O comando...... `echo`

Útil comoecoÉ, não deve ser uma surpresa que issoapareceu pela primeira vez cedo na Segunda Edição do UNIX dos Laboratórios Bell 1em 1972. Estaversão inicial aceitou nenhuma opção 2— embora a página de manual não diga explicitamente que a saída é seguida por um caractere de nova linha, a descrição de escrever "como uma linha" parece implicar isso. NaSétima Edição do UNIX, a página de manual 3torna isso claro, e também apresenta a adição doA cidade de Nova York está se preparando para uma semana histórica, com a expectativa de que o lançamento do novo modelo de carro elétrico da Tesla, o Model S Plaid, possa bater recordes de velocidade e eficiência. O evento, agendado para a próxima segunda-feira, 15 de maio, no centro de testes de autômos da Tesla em Freemont, Califórnia, promete ser um marco na indústria automotiva. O Model S Plaid é projetado para alcançar uma aceleração de 0 a 100 km/h em menos de 2 segundos, tornando-o o carro elétrico mais rápido do mundo. Com um preço estimado de US$ 150.000, o veículo representa um salto significativo na tecnologia de veículos elétricos, oferecendo uma experiência de condução excepcional e sustentabilidade ambiental. A Tesla tem sido pioneira na inovação de carros elétricos, e este lançamento é visto como mais um passo em direção à adoção generalizada de veículos ecológicos. Os entusiastas dos carros e investidores estão ansiosos para testemunhar o que a Tesla pode alcançar com esta nova criação, que promete revolucionar as estradas.opção, que causaecoPara imprimir os argumentossempreUm caractere de nova linha final.Oitava Edição do Unix eco 4ganhou aea opção que permite o uso de certos códigos de escape da linguagem de programação C.

Essas variações causaram diferenças de comportamento entre diferentes versões doecho. Ao executarecho -n algono seu sistema, o texto "algo" será exibido sem uma quebra de linha, ou "-n algo" seguido por uma quebra de linha? As coisas ficam ainda mais complexas quando os argumentos de comando incluem expansões de parâmetros ou caminhos. Se houver arquivos chamados "-n" e "algo" no diretório atual, o que acontece?Ecoa *A saída depende se a sua versão trata isso como uma opção, assim como a pergunta anterior.EcoaTrata-nComo uma opção. Não é possível contornar essa ambiguidade citando ou escapando o "*", porque isso apenas faz com que o ecoe um asterisco literal.EcoaPara imprimir um asterisco literal.

Utilizando exemplos de utilitários GNU no Debian 12; tanto o utilitário "echo" quanto o comando embutido "echo" do bash reconhecem "-n" como uma opção.

`ls -1
-n
algo
`
`echo *
algo`
# O prompt do shell está na mesma linha porque "-n" foi tratado como uma opção para echo
`echo "*"
*`

A solução foi criar um novo utilitário, que é o primeiro Curio UNIX do dia:printfEste comando permite que um usuário imprima texto de maneira semelhante à função com o mesmo nome na linguagem de programação C. Vocêexecuta printf 5seguido por uma string de formato, seguido por zero ou mais argumentos. Caracteres de nova linha não são impressos a menos que especificado pela string de formato ou pelos argumentos.

Para usarprintfpara imprimir "algo" sem uma nova linha, seria simplesmenteprintf algoIsso demonstra que você não precisa de argumentos — neste exemplo, a string de formato é apenas um conjunto de caracteres regulares a serem exibidos. Se você quiser um caractere de nova linha no final,printf "algo\n"proporcionaria isso. (Neste caso, a string de formato precisa ser entre aspas para que o "\n" não seja interpretado pelo shell.) Além de "\n" para uma nova linha, você também pode usar "\a" para um alerta (toca o sino do terminal), "\b" para uma backspace, "\f" para um form feed, "\r" para um retorno de carroça, "\t" para uma tabulação horizontal, "\v" para uma tabulação vertical e "\\" para obter um backslash literal. Além desses caracteres especiais, qualquer byte arbitrário pode ser incluído usando um backslash seguido por um a três dígitos octais; no entanto, pode ser difícil prever o que será impresso, pois pode variar dependendo do conjunto de caracteres usado pelo terminal. É mais seguro e portátil aderir aos caracteres pré-definidos sempre que possível.

OO realA magia doprintfA utilidade vem da utilização de "especificações de conversão" na string de formato. Provavelmente a mais simples dessas especificações para explicar é o "%s" - representa uma string de qualquer comprimento. O comandoprintf "Olá, %s, como você está?\n"seguido por uma lista de nomes imprimiria o saudação para cada nome, colocando-o no lugar ocupado pelo "%s".

$ printf "Olá, %s, como você está?\n" Alice Bob Carol

A string de formato é reutilizada tantas vezes quantas forem necessárias para consumir todos os argumentos. Veja, por exemplo, o comandoOlá, %s, você já conheceu %s?Se este comando for executado com dois argumentos de nome, ele imprimirá a frase em uma linha, utilizando ambos os nomes. Se executado com quatro argumentos de nome, ele imprimirá a frase duas vezes, uma vez com os primeiros dois nomes e novamente com os segundos dois nomes. Se você fornecer apenas três nomes, o último "%s" na especificação de conversão será substituído por uma string vazia.

Olá, %s, você já conheceu %s?

Três outros itens também podem ser fornecidos em cada especificação de conversão: bandeiras, largura do campo e precisão. O significado exato desses depende do tipo de caractere especificador de conversão que você está usando. Para "%s", usar um "-" como bandeira causa a justificação à esquerda do texto em vez da justificação à direita padrão, uma largura de campo faz com que o campo impresso tenha pelo menos o comprimento do número fornecido, e a precisão limita o número de bytes escritos da string para o valor fornecido.

Exemplo de %s com um valor de precisão:

Embora "%s" seja provavelmente a especificação de conversão mais comumente usada, outras estão disponíveis. Um conjunto inteiro delas é dedicado a imprimir valores inteiros como um número decimal com sinal, decimal sem sinal, octal sem sinal ou hexadecimal sem sinal. Eles também podem levar bandeiras, largura de campo e precisão. Acho que os detalhes e nuances de todos eles são complexos demais para explicar claramente aqui, então vou apenas referi-lo à especificação de notação de formato de arquivo POSIX.Especificação de notação de formato de arquivo POSIX 6 .

Tenha em mente que, ao contrário do ...A tradução do texto fornecido para o português brasileiro é: `printf`Função na linguagem de programação C, aA tradução do texto fornecido para o português brasileiro é: `print()`utilidadetexto: "Notícia: Um novo estudo revela os impactos da mudança climática nas comunidades costeiras. Os pesquisadores descobriram que o aumento do nível do mar está causando erosão significativa em praias e dunas, ameaçando a infraestrutura e os meios de subsistência locais."É obrigatório aceitar especificações de conversão para números de ponto flutuante. Embora algumas implementações possam suportar isso, scripts destinados a serem portáteis devem limitar-se ao conjunto restrito exigido pelo padrão POSIX (%d, %i, %o, %u, %x, %X, %c e %s, além de %b e %% descritos abaixo).

Mais duas especificações de conversão valem ser mencionadas. A primeira é...apenasRequerido pela norma para oprintfUma utilidade, não a função C, e é "%b". Isso é o mesmo que "%s", exceto que certas sequências de escape de barra invertida no argumento serão tratadas de forma especial. Isso inclui todas as descritas acima.ExcetoPara o que usa dígitos octais para representar um byte. Em um argumento, isso é representado em vez disso por "\0" seguido de um a três dígitos octais. Uma sequência de escape adicional aceita é "\c" — isso não imprime nada por si só, mas causaprintfPara interromper imediatamente a saída.

A especificação final de conversão é "%%", que simplesmente sai um literal "%". Não se pode usar um "% puro" na string de formato, porqueA tradução do texto fornecido para o português brasileiro é: `print()`Exemplo assumindo que o arquivo hipotético "/dev/batterycharge" em seu laptop exibe o nível de carga da bateria (42% neste caso). Como você pode ver, em alguns casos uma mensagem de erro pode ser exibida, mas em outros ele pode simplesmente se comportar de maneira inesperada sem reclamar. O utilitário "printf" do GNU e o "printf" interno do bash ambos suportam "%e" como uma especificação de conversão como uma extensão do POSIX.

Exemplo assumindo que o arquivo hipotético "/dev/batterycharge" em seu laptop exibe o nível de carga da bateria (42% neste caso). Como você pode ver, em alguns casos uma mensagem de erro pode ser exibida, mas em outros ele pode simplesmente se comportar de maneira inesperada sem reclamar. O "printf" do GNU e o "printf" interno do bash ambos suportam "%e" como uma especificação de conversão como uma extensão do POSIX.

$ cat /dev/batterycharge
42
# Erro
$ printf "Nível de carga do seu laptop é $(cat /dev/batterycharge)%.\n"
bash: printf: `\': caractere de formato inválido
Nível de carga do seu laptop é 42$ # Prompt do shell aparece aqui do erro
# Correto
$ printf "Nível de carga do seu laptop é $(cat /dev/batterycharge)%.\n"
Nível de carga do seu laptop é 42%.
# Próximo trata %e como especificador, com espaço e "l" como flags
$ printf "Seu laptop tem $(cat /dev/batterycharge)% de carga.\n"
Seu laptop tem 42 0.000000e+00 de carga.
# Como nenhum argumento foi dado, "0" foi usado para o valor a converter

Vamos voltar à situação que eu estava descrevendo com...eco...%s %s*printf "%s " *Que não trataria o "-n" como uma opção. No entanto, a saída pode parecer um pouco estranha porque não haveria um caractere de nova linha no final. Poderíamos inserir um caractere de nova linha usando "%b" em vez de "%s" e seguindo a estrela com um "\n\c" como o segundo argumento. O "\c" está lá para evitar que o espaço final na string de formato seja impresso após a nova linha.

`ls -1
-n
algo
$ printf "%s " *
-n algo # Nenhuma nova linha foi impressa aqui
$ printf "%b " * "\n"
-n algo
 $ # Há uma nova linha, mas também um espaço inválido antes do prompt da shell
$ printf "%b " * "\n\c"
-n algo
$ # Sem espaço antes do prompt da shell desta vez`

Portanto, usar a especificação de conversão "%b" pode resolver um problema, mas também introduz outro. Argumentos que incluem uma barra invertida podem ser interpretados como sequências de escape, e muitos sistemas estão bem em permitir barras invertidas nos nomes de arquivos. Em casos onde você está usando apenas a`printf`utilidadeexibiçãogeralmente não é um grande problema se a saída parecer um pouco estranha.

# GNU "ls" exibe nomes de arquivos que contêm uma barra invertida em aspas simples
$ ls -1
maçã
banana
'\cereja'
durian
$ printf "%b " * "\n\c"
maçã banana $ #"\c" em "\cereja" interrompe a saída imediatamente

OA função de impressãoUma utilidadeParece ter aparecido pela primeira vez na nona edição do UNIX em 1986 7Embora a página de manual mais antiga que consegui encontrarSeja da décima edição. Sua primeira aparição no BSD parece ser de 1990 na versão 4.3 Reno 8O(sem tradução, mantendo o número e formato) 9Dois anos depois, foi adicionado ao número 4 da Especificação CAE do The Open Group. Do que eu posso ver, não parecia estar no Sistema III da AT&T — presumivelmente oprintfutilitário chegou ao Sistema V em algum momento, mas achei difícil rastreá-lo.

Emboraechoainda seja adequado para uso quando você tem certeza de que deseja imprimir um caractere de nova linha no final e nenhum dos argumentos começar com um hífen, considere usar oprintfutilitário em vez disso para exibir texto. Ele oferece mais flexibilidade e recursos do que você é garantido de obter comecoEmbora exija um pouco de planejamento para construir uma string de formato adequada e argumentos, isso não é necessariamente uma coisa ruim, pois o autor do script...deveriaEstou pensando no que poderia acontecer se for chamado com textos ou nomes de arquivos "estranhos".

Este episódio também serve como um bom argumento para ter cuidado ao nomear arquivos — muitos sistemas de arquivos permitem o uso de hífens, caracteres de controle, aspas e, potencialmente, qualquer caractere exceto uma barra ou um byte nulo em um nome de arquivo. Como vimos, alguns desses caracteres podem criar problemas para utilitários padrão. Embora possa parecer limitante, especialmente para pessoas que não falam inglês, os nomes de arquivos mais seguros a serem usados em um sistema semelhante ao UNIX consistem apenas em caracteres do conjunto"conjunto de caracteres de nome de arquivo portátil" conforme definido pelo POSIX 10E onde está o primeiro personagem?texto: "Notícia: Uma nova pesquisa revela que a taxa de desemprego nos Estados Unidos caiu para 3,5% no último trimestre, marcando uma tendência positiva no mercado de trabalho."Este conjunto inclui as letras minúsculas e maiúsculas "a" a "z", os números "0" a "9" e o ponto, sublinhado e traço. Notavelmente, elenãoinclui o caractere de espaço.

Isso me leva a outro curiosidade do UNIX que eu acabei de descobrir enquanto pesquisava este episódio. Éa ferramenta pathchk de utilitário 11. Pode ser executada com um ou mais strings como argumentos, verifica cada uma contra um conjunto de regras para nomes de caminho e exibe uma mensagem de erro para cada problema encontrado. Por padrão, verifica os seguintes limites no sistema onde é executada: número máximo de bytes no caminho completo, número máximo de bytes em qualquer componente do caminho, todas as sequências de bytes devem ser válidas no diretório dado, e o usuário executando o programa deve ter acesso a todos os diretórios referenciados. Se executada com oA cidade de São Paulo registrou um aumento significativo no número de casos de COVID-19 nas últimas semanas, levando as autoridades de saúde a implementar medidas restritivas para controlar a propagação do vírus. De acordo com o último relatório da Secretaria de Saúde, foram confirmados 5.234 novos casos e 72 óbitos relacionados à doença na última terça-feira (06/07). As medidas incluem o fechamento de bares e restaurantes às 20h, limitação de aglomerações em locais públicos e incentivo ao trabalho remoto sempre que possível. O prefeito Bruno Covas destacou a importância da colaboração da população para superar esse momento crítico. A campanha de vacinação continua sendo uma estratégia fundamental na luta contra a pandemia. Até o momento, mais de 4,5 milhões de paulistas receberam a primeira dose da vacina, e mais de 3,2 milhões completaram o esquema vacinal.Em vez desses limites, ele verifica contra os limites do POSIX: um máximo de 256 bytes no caminho completo, um máximo de 14 bytes em cada componente do caminho, e cada componente deve incluir apenas caracteres do conjunto portátil.A cidade de São Paulo registrou um aumento significativo no número de casos de COVID-19 nas últimas semanas, levando as autoridades de saúde a implementar medidas restritivas para controlar a propagação do vírus. De acordo com o último relatório da Secretaria de Saúde, foram confirmados 5.234 novos casos e 72 óbitos relacionados à doença na última terça-feira (06/07). As medidas incluem o fechamento de bares e restaurantes às 20h, além do incentivo ao trabalho remoto sempre que possível. As escolas públicas da cidade também foram orientadas a adiar o retorno presencial às aulas, que inicialmente estava previsto para o dia 8 de agosto. Especialistas em saúde pública alertam que o aumento dos casos pode ser atribuído à relaxamento das medidas de distanciamento social e ao aumento das atividades econômicas. Eles enfatizam a importância do uso contínuo de máscaras, higiene das mãos e o respeito ao isolamento social para frear a onda de contágios.A opção adiciona avisos se algum componente começar com um "-" ou se o caminho estiver completamente vazio. Embora o status de saída indique se os verificações foram bem-sucedidas ou não, eu não acho que isso seja suficiente.Rota de verificaçãoA utilidade é adequada para ser usada de forma automatizada, pois a redação exata da sua saída não é especificada e as verificações não podem ser selecionadas individualmente. No entanto, pode ser utilizada interativamente para validar caminhos que você não tem certeza. Consulte a especificação ligada para detalhes completos.

Referências:

  1. Um Leitor de UNIX para Pesquisa: Tabelas Combinadas de ConteúdoO texto não está disponível na URL fornecida. Não é possível realizar a tradução sem o conteúdo original. Por favor, verifique a URL ou forneça o texto diretamente para a tradução.
  2. Um Leitor de UNIX de Pesquisa: Segunda Edição do Manual de Página echo do UNIX(embora esta página tenha "v1" digitado no topo, a data e as tabelas de conteúdos indicam que apareceu pela primeira vez na v2, também conhecida como Segunda Edição) https://archive.org/details/a_research_unix_reader/page/n22/mode/1up
  3. Página de manual da sétima edição do UNIX echoO texto fornecido parece estar incompleto ou incorreto, pois o link indicado não leva a um conteúdo legível. Não há um texto jornalístico para traduzir. Por favor, verifique e forneça o texto correto.
  4. Página de manual da oitava edição do UNIX echoO texto fornecido parece estar incompleto ou incorreto, pois o link indicado não leva a um conteúdo legível. Não há um texto jornalístico para traduzir. Por favor, verifique e forneça o texto correto.
  5. Especificação de impressãoEspecificação de Formato de Arquivo: A página fornece detalhes sobre a sintaxe e o uso da função `printf` para formatação e saída de dados em sistemas Unix.
  6. Notação de Formato de Arquivo: Uma especificação técnica que define como os arquivos devem ser formatados e representados.https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html: Este link leva ao capítulo 5 da especificação "Base Definitions" da Open Group, que abrange vários aspectos dos sistemas Unix.
  7. A Research UNIX Reader: Ninth Edition - Tabela de Conteúdo: Uma coleção de artigos e documentos históricos sobre o sistema operacional UNIX, incluindo informações sobre sua evolução e uso em pesquisas.https://archive.org/details/a_research_unix_reader/page/n95/mode/1up: Acesso a uma página específica da edição de 9ª série do "Research UNIX Reader", que pode conter um índice ou sumário detalhado.
  8. Manual de Página UNIX echo/printf - Décima Edição: Documentação técnica detalhada sobre as funções `echo` e `printf` no sistema operacional UNIX, incluindo exemplos de uso.https://man.cat-v.org/unix_10th/1/echo: Página do manual de usuário para a função `echo` na 10ª edição do UNIX, explicando suas opções e sintaxe.
  9. Página de manual 4.3BSD Reno printfConsulte a documentação do sistema para obter informações sobre o comando `printf`.
  10. Definição: Conjunto de Caracteres de Nome de Arquivo Portátil.Acesse a especificação completa no site da Open Group para entender os padrões de caminhos.
  11. Especificação do Pathchk, uma ferramenta de validação de caminhos.Saiba mais sobre o utilitário Pathchk e suas funcionalidades.

Forneça seu feedback sobre este episódio.Compartilhe suas opiniões e sugestões para melhorias.Participe da discussão sobre este tema..

Fonte
Hacker Public Radio
Abrir original ↗
Esta notícia foi útil?

Debates 0

Seja o primeiro a contribuir com o debate.

Difunda suas informações e promova seu argumento

Não se acanhe de publicar alguma informação ou dado que possa ser positivo ou útil.

Para participar do debate, entre com sua conta ou crie uma gratuita.