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 / 771394
Accepted
malat
malat
Asked: 2024-03-01 16:18:11 +0800 CST2024-03-01 16:18:11 +0800 CST 2024-03-01 16:18:11 +0800 CST

Como posso converter caracteres de largura total em caracteres de meia largura (e vice-versa)?

  • 772

Aqui está o meu problema simples: como posso converter meia largura em largura total na linha de comando. Achei que isso estaria embutido na minha iconvlinha de comando, mas não encontrei nada aqui:

$ iconv  -l | grep -i full
-> nothing
$ iconv  -l | grep -i half
-> nothing

A entrada típica seria:

$ echo -n "Ab9876543210" | iconv -f utf8 -t utf16be | hexdump -C
00000000  ff 21 00 62 ff 19 ff 18  ff 17 ff 16 ff 15 ff 14  |.!.b............|
00000010  ff 13 ff 12 ff 11 ff 10                           |........|
00000018
character-encoding
  • 1 1 respostas
  • 217 Views

1 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-03-01T16:49:04+08:002024-03-01T16:49:04+08:00

    Se você tiver o uconvutilitário das ferramentas ICU ( icu-devtoolspacote em sistemas operacionais baseados em Debian):

    $ echo 'Ab9876543210' | uconv -x Fullwidth-Halfwidth
    Ab9876543210
    

    (cuidado, ele também converte caracteres que normalmente têm largura total, como os dos scripts coreano ou japonês, em sua representação de meia largura).

    Mude para Halfwidth-Fullwidthpara o inverso.

    Caso contrário, e você estiver interessado apenas em converter as variantes de largura total dos caracteres imprimíveis ASCII:

    $ echo 'Ab9876543210' | perl -C -pe 'y/\x{ff01}-\x{ff5e}/!-~/'
    Ab9876543210
    

    Ou também convertendo U+3000 (espaço ideográfico) para espaço ASCII:

    $ echo 'Ab9876543210' | perl -C -pe 'y/\x{3000}\x{ff01}-\x{ff5e}/ !-~/'
    Ab9876543210
    
    curl -s https://www.unicode.org/Public/UNIDATA/UnicodeData.txt | grep '<wide>'
    

    Irá revelar alguns extras que são variantes de largura total de alguns caracteres não ASCII, que você pode adicionar à lista.

    perl -C -pe 'y/\x{3000}\x{ff01}-\x{ff60}\x{ffe0}-\x{ffe6}/ !-~\x{2985}\x{2986}\xa2\xa3\xac\xaf\xa6\xa5\x{20a9}/'
    

    (e a pesquisa <narrow>mostrará as variantes de meia largura de alguns caracteres normalmente de largura total, mas é uma lista grande e com intervalos não contíguos, portanto, adicioná-los tornaria a expressão muito maior).

    Em alguns sistemas, você pode fazer o mesmo trse estiver no código do idioma C.UTF-8, não com as versões atuais do GNU tr, a menos que seja corrigido pelo fornecedor do seu sistema operacional .

    $ uname
    FreeBSD
    $ echo 'Ab9876543210' | LC_ALL=C.UTF-8 tr $'\u3000\uff01-\uff5e' ' !-~'
    Ab9876543210
    

    (também assumindo um shell com suporte para zsh's $'\uXXXX').

    Para a conversão reversa, basta alterar y/from/to/para y/to/from/.

    perltambém possui uma interface para os dados Unicode em seu Unicode::UCDmódulo, então você também pode fazer:

    perl -C -MUnicode::UCD=charprop -pe '
      s{\p{Decomposition_Type: Wide}}{
        $cache{$&} //= charprop(ord($&), "Decomposition_Mapping")
      }ge'
    

    Embora seja bastante lento, mesmo que seja mitigado aqui pelo uso de cache. Veja perldoc perlunipropse perldoc Unicode::UCDpara detalhes.

    Ou usando a decomposição NFKD para os caracteres que possuem um tipo de decomposição amplo :

    perl -MUnicode::Normalize=NFKD -C -pe 's/\p{Dt=Wide}/NFKD$&/ge'
    

    Se for para converter para ASCII, pelo menos em sistemas GNU, iconv -t ASCII//translittambém converteria esses (e mais caracteres para sua representação de caractere ASCII mais próxima¹)

    $ echo 'Stéphane' | iconv -t ASCII//translit
    Stephane
    

    Obviamente, não há como fazer o inverso.

    De qualquer forma, aqui, não é a conversão do mesmo caractere de charset para charset que você deseja fazer, mas alguma forma de transliteração de alguns caracteres para outros caracteres.

    iconv -llike uconv -llista as codificações/conjuntos de caracteres suportados. uconv -Llista os transliteradores. GNU iconvsó tem aquilo //translitque dá uma aproximação possível se o caractere não existir no conjunto de caracteres de destino (além //ignorede apenas descartá-los).


    ¹ ou caracteres como em æ-> aeou ffi-> ffique, a propósito, não possuem formatos de largura total, mas já foram aproximados; por exemplo, você pode querer converter affixpara affixem vez de affixconverter para largura total, o que nenhuma das soluções mencionadas aqui trata.

    • 5

relate perguntas

  • Qual é o caminho certo para codificar em base64 um arquivo binário no CentOS 7?

  • Codificação não nula inesperada de /proc/<pid>/cmdline

  • Como traduzir caracteres Unicode? [duplicado]

  • Problemas com tremas (não consigo digitar no terminal + não consigo abrir arquivos)

  • Como fazer com que `less` entenda a página de código?

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