Eu me pergunto por que a maioria das soluções modernas criadas usando o Perl não habilita o UTF-8 por padrão.
Entendo que existem muitos problemas herdados para scripts Perl principais, nos quais isso pode quebrar as coisas. Mas, do meu ponto de vista, na 21 st século, novos e grandes projetos (ou projectos com uma grande perspectiva) deve fazer o seu software UTF-8 prova a partir do zero. Ainda não vejo isso acontecendo. Por exemplo, o Moose habilita estritos e avisos, mas não Unicode . Moderno: o Perl também reduz o padrão, mas não o manuseio UTF-8.
Por quê? Existem algumas razões para evitar o UTF-8 em projetos Perl modernos no ano de 2011?
Comentar @tchrist ficou muito tempo, então eu estou adicionando aqui.
Parece que não me deixei claro. Deixe-me tentar adicionar algumas coisas.
Chris e eu vemos a situação da mesma maneira, mas nossas conclusões são completamente opostas. Concordo que a situação com o Unicode é complicada, mas é por isso que nós (usuários e codificadores Perl) precisamos de uma camada (ou pragma) que torne o manuseio de UTF-8 o mais fácil possível nos dias de hoje.
Se Chris apontou muitos aspectos a serem abordados , vou ler e pensar sobre eles por dias ou até semanas. Ainda assim, este não é o meu ponto. O tchrist tenta provar que não existe uma única maneira "de habilitar o UTF-8". Eu não tenho muito conhecimento para discutir isso. Então, continuo a viver exemplos.
Eu brinquei com Rakudo e o UTF-8 estava lá quando eu precisava . Não tive nenhum problema, apenas funcionou. Talvez haja alguma limitação em algum lugar mais profundo, mas, no início, tudo que eu testei funcionou como eu esperava.
Isso também não deveria ser um objetivo no Perl 5 moderno? Enfatizo mais: não estou sugerindo o UTF-8 como o conjunto de caracteres padrão para o Perl principal; sugiro a possibilidade de acioná-lo rapidamente para aqueles que desenvolvem novos projetos.
Outro exemplo, mas com um tom mais negativo. Estruturas devem facilitar o desenvolvimento. Alguns anos atrás, tentei frameworks da web, mas apenas os joguei fora porque "ativar o UTF-8" era muito obscuro. Não encontrei como e onde conectar o suporte a Unicode. Foi tão demorado que achei mais fácil seguir o caminho antigo. Agora eu vi aqui que havia uma recompensa para lidar com o mesmo problema com o Mason 2: Como limpar o Mason2 UTF-8? . Portanto, é uma estrutura bastante nova, mas usá-la com UTF-8 precisa de um conhecimento profundo de seus componentes internos. É como um grande sinal vermelho: PARE, não me use!
Eu realmente gosto de Perl. Mas lidar com Unicode é doloroso. Eu ainda me pego correndo contra as paredes. De alguma forma, o tchrist está certo e responde às minhas perguntas: novos projetos não atraem UTF-8 porque é muito complicado no Perl 5.
Sinto muito, mas concordo com @tchrist - UTF-8 é extremamente difícil. Não há estrutura ou ferramenta que apenas "vire um switch" e lide com isso corretamente. É algo em que você deve pensar diretamente ao projetar seu aplicativo - não é algo que qualquer tipo de estrutura ou linguagem possa manipular para você. Se o rakudo funcionou para você, você não foi aventureiro o suficiente com seus casos de teste - pois serão necessários vários exemplos da resposta do @ tchrist e o açougueiro.
O que exatamente você espera que o Moose ou o Modern :: Perl façam? Transformar magicamente dados de caracteres codificados aleatoriamente em arquivos e bancos de dados em dados válidos novamente?
— Jrockway 31/05
O que isso significa? Moose não tem nada a ver com manipulação de texto. Por que ela deveria saber sobre codificação de caracteres e muito menos escolher uma padrão para você? (De qualquer forma, a razão pela qual os pragmas listados não tocam na codificação é porque a convenção é que os pragmas Perl afetem o comportamento lexical . Supondo que o mundo inteiro, incluindo outros módulos, seja UTF-8, é simplesmente a coisa errada a fazer . Isto não é PHP ou ruby aqui).
(Também ... "mais Modern Perl Apps" ruptura em UTF-8 Eu certamente nunca escrevi um aplicativo, Perl ou não, isso não é Unicode-clean?.)
Nb. tchrist (Tom Christiansen) postou seu [ training.perl.com/OSCON2011/index.html Materiais de Tom Christiansen para OSCON 2011] sobre o Unicode. O título "Tiroteio de suporte Unicode: o bom, o ruim e o (principalmente) feio" fala sobre o suporte ao Unicode em diferentes linguagens de programação. Somente o Google Go e o Perl5 têm suporte para Unicode completo, apenas o Google Go (sem mencionar o Perl6).
℞ ℞ : 𝟕 𝘿𝙞𝙨𝙘𝙧𝙚𝙩𝙚 𝙍𝙚𝙘𝙤𝙢𝙢𝙚𝙣𝙙𝙖𝙩𝙞𝙤𝙣𝙨
Defina seu PERL_UNICODEenvariável como AS. Isso faz com que todos os scripts Perl decodifiquem @ARGVcomo strings UTF ‑ 8 e define a codificação dos três stdin, stdout e stderr como UTF ‑ 8. Ambos são efeitos globais, não lexicais.
Na parte superior do seu arquivo de origem (programa, módulo, biblioteca, dohickey), afirme com destaque que você está executando o perl versão 5.12 ou superior através de:
Ative avisos, uma vez que a declaração anterior ativa apenas restrições e recursos, não avisos. Também sugiro promover avisos Unicode em exceções, portanto, use essas duas linhas, não apenas uma delas. Nota, contudo, que sob v5.14, a utf8classe de advertência compreende três outros subwarnings que podem ser ativados separadamente: nonchar, surrogate, e non_unicode. Estes você pode querer exercer maior controle sobre.
Declare que esta unidade de origem está codificada como UTF ‑ 8. Embora outrora esse pragma fizesse outras coisas, agora serve a esse único propósito único e a nenhum outro:
Declare que qualquer coisa que abra um identificador de arquivo nesse escopo lexical, mas não em outro lugar, deve assumir que esse fluxo é codificado em UTF-8, a menos que você indique o contrário. Dessa forma, você não afeta o código de outro módulo ou outro programa.
Ativar caracteres nomeados via \N{CHARNAME}.
Se você tem um DATAidentificador, deve definir explicitamente sua codificação. Se você deseja que este seja UTF ‑ 8, diga:
É claro que não há fim de outros assuntos com os quais você possa se preocupar, mas estes serão suficientes para aproximar a meta do estado de "fazer tudo funcionar apenas com a UTF-8", embora para um sentido um pouco enfraquecido desses termos.
Um outro pragma, embora não seja relacionado ao Unicode, é:
É fortemente recomendado.
🌴 🐪🐫🐪 🌞 𝕲𝖔 𝕿𝖍𝖔𝖚 𝕯𝖔 𝕷𝖎𝖐𝖊𝖜𝖎𝖘𝖊 🌞 🐪🐫🐪 🐁
🎁 🐪 𝕭𝖔𝖎𝖑𝖊𝖗⸗𝖕𝖑𝖆𝖙𝖊 𝖋𝖔𝖗 𝖀𝖓𝖎𝖈𝖔𝖉𝖊⸗𝕬𝖜𝖆𝖗𝖊 𝕮𝖔𝖉𝖊 🐪
Meu próprio padrão hoje em dia tende a ficar assim:
🎅 𝕹 𝖔 𝕸 𝖆 𝖎 𝖈 𝕭 𝖚 𝖑 𝖑 𝖊 𝖙.
Dizendo que "Perl deveria [de alguma forma! ] ativar o Unicode por padrão "nem começa a pensar em dizer o suficiente para ser marginalmente útil em algum tipo de caso raro e isolado. Unicode é muito mais do que apenas um repertório de caracteres maior; é também como esses personagens interagem de muitas, muitas maneiras.
Até as medidas mínimas simplistas que (algumas) as pessoas pensam que desejam têm garantia de quebrar miseravelmente milhões de linhas de código, código que não tem chance de "atualizar" para o seu novo e admirável mundo novo corajoso moderna modernidade .
É muito mais complicado do que as pessoas fingem. Pensei muito sobre isso nos últimos anos. Eu adoraria ser mostrado que estou errado. Mas acho que não sou. O Unicode é fundamentalmente mais complexo do que o modelo que você deseja impor a ele, e aqui há complexidade que você nunca pode varrer para debaixo do tapete. Se você tentar, você quebrará seu próprio código ou o de outra pessoa. Em algum momento, você simplesmente precisa analisar e descobrir o que é o Unicode. Você não pode fingir que é algo que não é.
Faz de tudo para facilitar o Unicode, muito mais do que qualquer outra coisa que eu já usei. Se você acha que isso é ruim, tente outra coisa por um tempo. Então volte para 🐪: ou você retornará a um mundo melhor, ou trará consigo o conhecimento do mesmo para que possamos fazer uso de seu novo conhecimento para melhorar these essas coisas.
💡 𝕴𝖉𝖊𝖆𝖘 𝖋𝖔𝖗 𝖆 𝖀𝖓𝖎𝖈𝖔𝖉𝖊 𝕬𝖜𝖆𝖗𝖊 🐪 𝕷𝖆𝖚𝖓𝖉𝖗𝖞 𝕷𝖎𝖘𝖙 💡
No mínimo, aqui estão algumas coisas que parecem ser necessárias para "ativar o Unicode por padrão", como você coloca:
Todo o código fonte deve estar em UTF-8 por padrão. Você pode conseguir isso com use utf8ou export PERL5OPTS=-Mutf8.
O DATAidentificador should deve ser UTF-8. Você precisará fazer isso por pacote, como em binmode(DATA, ":encoding(UTF-8)").
Os argumentos do programa para scripts devem ser entendidos como UTF-8 por padrão. export PERL_UNICODE=A, ou perl -CA, ou export PERL5OPTS=-CA.
Os fluxos de entrada, saída e erro padrão devem ter como padrão UTF-8. export PERL_UNICODE=Spara todos eles, ou I, Oe / ou Epor apenas alguns deles. Isto é como perl -CS.
Quaisquer outros identificadores abertos por 🐪 devem ser considerados UTF-8, a menos que declarado de outra forma; export PERL_UNICODE=Dou com ie opara determinados deles; export PERL5OPTS=-CDpodia funcionar. Isso faz -CSADpara todos eles.
Cubra as duas bases e todos os fluxos que você abrir export PERL5OPTS=-Mopen=:utf8,:std. Veja uniquote .
Você não deseja perder erros de codificação UTF-8. Tente export PERL5OPTS=-Mwarnings=FATAL,utf8. E certifique-se de que seus fluxos de entrada sejam sempre binmodeadequados :encoding(UTF-8), e não apenas adequados :utf8.
Os pontos de código entre 128 e 255 devem ser entendidos por 🐪 como os pontos de código Unicode correspondentes, e não apenas valores binários não autorizados. use feature "unicode_strings"ou export PERL5OPTS=-Mfeature=unicode_strings. Isso fará uc("\xDF") eq "SS"e "\xE9" =~ /\w/. Um simples export PERL5OPTS=-Mv5.12ou melhor também vai conseguir isso.
Os caracteres Unicode nomeados não são ativados por padrão, portanto adicione export PERL5OPTS=-Mcharnames=:full,:short,latin,greekou alguns deles. Veja uninames e tcgrep .
Você quase sempre precisa acessar as funções do módulo padrão deUnicode::Normalize vários tipos de decomposições. export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKDe, em seguida, sempre execute os itens recebidos pelo NFD e os itens de saída do NFC. Ainda não tenho uma camada de E / S para elas, mas veja nfc , nfd , nfkd e nfkc .
Comparação de strings em 🐪 usando eq, ne, lc, cmp, sort, & c & cc estão sempre errados. Então, em vez de @a = sort @b, você precisa @a = Unicode::Collate->new->sort(@b). Pode muito bem adicionar isso ao seu export PERL5OPTS=-MUnicode::Collate. Você pode armazenar em cache a chave para comparações binárias.
🐪 built-ins gostam printfe writefazem a coisa errada com dados Unicode. Você precisa usar o Unicode::GCStringmódulo para o primeiro, e ambos, e também o Unicode::LineBreakmódulo , para o último. Veja uwc e unifmt .
Se você quiser que eles contem como números inteiros, será necessário executar suas \d+capturas através da Unicode::UCD::numfunção porque o atoi (3) interno do 🐪 não é suficientemente inteligente no momento.
Você terá problemas de sistema de arquivos em sistemas de arquivos. Alguns sistemas de arquivos impõem silenciosamente uma conversão para NFC; outros silenciosamente impõem uma conversão para NFD. E outros fazem outra coisa ainda. Alguns até ignoram completamente o assunto, o que leva a problemas ainda maiores. Então você tem que fazer seu próprio manuseio de NFC / NFD para manter a sanidade.
Toda a sua 🐪 código envolvendo a-zou A-Ze tal deve ser mudado , incluindo m//, s///e tr///. Deve destacar-se como uma bandeira vermelha gritante que seu código está quebrado. Mas não está claro como isso deve mudar. Obter as propriedades certas e entender suas dobras de caixa é mais difícil do que você imagina. Eu uso unichars e uniprops todos os dias.
O código que usa \p{Lu}é quase tão errado quanto o código que usa [A-Za-z]. Em \p{Upper}vez disso, você precisa usar e saber o motivo. Sim \p{Lowercase}e \p{Lower}são diferentes de \p{Ll}e \p{Lowercase_Letter}.
O código que usa [a-zA-Z]é ainda pior. E não pode usar \pLou \p{Letter}; ele precisa usar \p{Alphabetic}. Nem todos os alfabéticos são letras, você sabe!
Se você está procurando 🐪 variáveis ​​com /[\$\@\%]\w+/, então você tem um problema. Você precisa procurar /[\$\@\%]\p{IDS}\p{IDC}*/, e mesmo isso não está pensando nas variáveis ​​de pontuação ou nas variáveis ​​de pacote.
Se você estiver procurando por espaço em branco, deverá escolher entre \he \v, dependendo. E você nunca deve usar \s, pois NÃO SIGNIFICA [\h\v] , contrariamente à crença popular.
Se você estiver usando \npara um limite de linha, ou até mesmo \r\n, estará fazendo errado. Você tem que usar \R, o que não é o mesmo!
Se você não sabe quando e se deve chamar Unicode :: Stringprep , é melhor aprender.
As comparações que não diferenciam maiúsculas de minúsculas precisam verificar se duas coisas são as mesmas letras, independentemente de seus sinais diacríticos. A maneira mais fácil de fazer isso é com o módulo Unicode :: Collate padrão . Unicode::Collate->new(level => 1)->cmp($a, $b). Existem também eqmétodos e tal, e você provavelmente deve aprender sobre os matche substrmétodos, também. Essas são vantagens distintas sobre os 🐪 embutidos.
Às vezes isso ainda não é suficiente, e você precisa do módulo Unicode :: Collate :: Locale , como em Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b)vez disso. Considere que isso Unicode::Collate::->new(level => 1)->eq("d", "ð")é verdade, mas Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð")é falso. Da mesma forma, "ae" e "æ" são eqse você não usa códigos de idioma ou se usa o inglês, mas eles são diferentes no código de idioma islandês. O que agora? É difícil, eu lhe digo. Você pode jogar com o ucsort para testar algumas dessas coisas.
Considere como corresponder ao padrão CVCV (consoante, vogal, consoante, vogal) na sequência " niño ". Sua forma de NFD - que você se lembrava muito bem de ter colocado - se torna "nin \ x {303} o". O que você fará agora? Mesmo fingindo que uma vogal é [aeiou](o que está errado, a propósito), você também não poderá fazer algo assim (?=[aeiou])\X), porque mesmo no NFD um ponto de código como 'ø' não se decompõe ! No entanto, o teste será igual a um 'o' usando a comparação UCA que acabei de mostrar. Você não pode confiar no NFD, mas no UCA.
💩 𝔸 𝕤 𝕤 𝕦 𝕖 𝔹 𝕣 𝕠 𝕜 𝕖 𝕟 𝕟 𝕖 𝕤 💩.
E isso não é tudo. Há um milhão de suposições quebradas que as pessoas fazem sobre o Unicode. Até que eles entendam essas coisas, seu código will será quebrado.
Código que pressupõe que ele pode abrir um arquivo de texto sem especificar que a codificação está quebrada.
O código que assume que a codificação padrão é algum tipo de codificação de plataforma nativa está quebrado.
O código que assume que as páginas da Web em japonês ou chinês ocupam menos espaço no UTF-16 do que no UTF-8 está errado.
O código que assume que o Perl usa UTF-8 internamente está errado.
O código que assume que os erros de codificação sempre geram uma exceção está errado.
O código que assume pontos de código Perl limitados a 0x10_FFFF está incorreto.
O código que pressupõe que você pode definir $/algo que funcione com qualquer separador de linha válido está errado.
O código que assume a igualdade de ida e volta na dobra de caixa, como lc(uc($s)) eq $sou uc(lc($s)) eq $s, está completamente quebrado e errado. Considere que o uc("σ")e uc("ς") são ambos "Σ", mas lc("Σ")não podem retornar os dois.
O código que assume que cada ponto de código em minúsculas possui um maiúsculo distinto, ou vice-versa, está quebrado. Por exemplo, "ª"é uma letra minúscula sem maiúscula; considerando que ambos "ᵃ"e "ᴬ"são letras, mas não são letras minúsculas; no entanto, ambos são pontos de código em minúsculas sem as versões em maiúsculas correspondentes. Percebido? Eles não são \p{Lowercase_Letter}, apesar de serem ambos \p{Letter}e \p{Lowercase}.
O código que pressupõe que a alteração de maiúsculas e minúsculas não altera o comprimento da string está quebrado.
O código que assume que há apenas dois casos está quebrado. Também há titlecase.
O código que assume apenas letras com maiúsculas e minúsculas está quebrado. Além das letras, verifica-se que números, símbolos e até marcas têm maiúsculas e minúsculas. De fato, mudar o caso pode até fazer com que algo mude sua principal categoria geral, como \p{Mark}transformar-se em a \p{Letter}. Também pode mudar de um script para outro.
O código que assume que o caso nunca depende de localidade é quebrado.
O código que supõe que o Unicode fornece uma informação sobre as localidades POSIX está quebrado.
O código que pressupõe que você pode remover os sinais diacríticos para obter as letras ASCII básicas é mau, imóvel, quebrado, com dano cerebral, errado e justificativa para a pena capital.
O código que assume que diacríticos \p{Diacritic}e marcas \p{Mark}são a mesma coisa está quebrado.
Código que assume que \p{GC=Dash_Punctuation}cobre tanto quanto \p{Dash}está quebrado.
O código que assume traços, hífens e desvantagens são a mesma coisa que os outros, ou que existe apenas um de cada um, está quebrado e errado.
O código que assume que todo ponto de código ocupa não mais que uma coluna de impressão está quebrado.
O código que assume que todos os \p{Mark}caracteres ocupam zero colunas de impressão está quebrado.
Código que pressupõe que caracteres semelhantes são quebrados.
O código que assume que caracteres que não são parecidos não é semelhante está quebrado.
O código que assume que há um limite para o número de pontos de código em uma linha que apenas um \Xpode corresponder está errado.
O código que supõe que \Xnunca pode começar com um \p{Mark}caractere está errado.
O código que assume que \Xnunca pode conter dois \p{Mark}caracteres não está errado.
Código que assume que não pode ser usado "\x{FFFF}"está errado.
O código que assume um ponto de código não BMP que requer duas unidades de código UTF-16 (substitutas) codificará para dois caracteres UTF-8 separados, um por unidade de código, está incorreto. Não: codifica para um ponto de código único.
O código que transcodifica de UTF ‐ 16 ou UTF ‐ 32 com listas técnicas principais para UTF ‐ 8 é quebrado se colocar uma lista técnica no início do UTF-8 resultante. Isso é tão estúpido que o engenheiro deve remover as pálpebras.
O código que assume que o CESU-8 é uma codificação UTF válida está incorreto. Da mesma forma, o código que pensa codificar U + 0000 como "\xC0\x80"UTF-8 está quebrado e errado. Esses caras também merecem o tratamento palpebral.
O código que assume caracteres como >sempre aponta para a direita e <sempre para a esquerda está errado - porque na verdade não.
Código que pressupõe que, se você primeiro gera um caractere Xe depois um caractere Y, esses serão exibidos como XYincorretos. Às vezes não.
O código que supõe que o ASCII é bom o suficiente para escrever o inglês corretamente é estúpido, míope, analfabeto, quebrado, mal e errado. Fora com suas cabeças! Se isso parecer extremo demais, podemos comprometer: a partir de agora eles podem digitar apenas com o dedão do pé a um pé. (O restante será gravado no duto.)
O código que assume que todos \p{Math}os pontos de código são caracteres visíveis está errado.
O código que assume que \wcontém apenas letras, dígitos e sublinhados está incorreto.
O código que assume que ^e ~são sinais de pontuação está incorreto.
Código que assume que ütem um trema está errado.
Código que acredita que coisas como ₨qualquer letra contida está errado.
Código que acredita \p{InLatin}ser o mesmo que \p{Latin}é odiado violentamente.
Código que acredita que \p{InLatin}quase sempre é útil é quase certamente errado.
Código que acredita que, dado $FIRST_LETTERque é a primeira letra de algum alfabeto e $LAST_LETTERa última letra do mesmo alfabeto, que [${FIRST_LETTER}-${LAST_LETTER}]tem algum significado, quase sempre está completo, quebrado, errado e sem sentido.
O código que acredita que o nome de alguém só pode conter certos caracteres é estúpido, ofensivo e errado.
O código que tenta reduzir Unicode para ASCII não está apenas errado, seu autor nunca deve ter permissão para trabalhar na programação novamente. Período. Eu nem tenho certeza de que eles devam ver novamente, pois obviamente não os fez muito bem até agora.
O código que acredita que existe uma maneira de fingir que as codificações de arquivos de texto não existem é quebrado e perigoso. Poderia muito bem apontar o outro olho também.
O código que converte caracteres desconhecidos em ?está quebrado, estúpido, irracional e é contrário à recomendação padrão, que diz NÃO FAZER ISSO!RTFM por que não.
O código que acredita que pode adivinhar com segurança a codificação de um arquivo de texto não marcado é culpado de uma mistura fatal de arrogância e ingenuidade que apenas um raio de Zeus corrigirá.
O código que acredita que você pode usar 🐪 printflarguras para preencher e justificar os dados Unicode está quebrado e errado.
O código que acredita que, depois de criar com êxito um arquivo com um nome determinado, que quando você executa lsou readdirem seu diretório anexo, na verdade, você encontra esse arquivo com o nome em que foi criado, com erros, interrupções e erros. Pare de se surpreender com isso!
O código que acredita que o UTF-16 é uma codificação de largura fixa é estúpido, quebrado e errado. Revogue sua licença de programação.
O código que trata os pontos de código de um plano e de maneira diferente dos de qualquer outro plano é ipso facto quebrado e errado. Volte para a escola.
Código que acredita que coisas assim /s/isó podem corresponder "S"ou "s"estão quebradas e erradas. Você ficaria surpreso.
O código usado \PM\pM*para encontrar clusters de grafema em vez de usar \Xestá quebrado e errado.
As pessoas que desejam voltar ao mundo ASCII devem ser incentivadas de todo o coração a fazê-lo e, em homenagem a sua atualização gloriosa, devem receber gratuitamente uma máquina de escrever manual pré-elétrica para todas as suas necessidades de entrada de dados. As mensagens enviadas a eles devem ser enviadas através de um telégrafo com 40 caracteres por linha e entregues em mão por um mensageiro. PARE.
😱 𝕾 𝖀 𝕸 𝕸 𝕽 𝖄 😱
Não sei quanto mais "Unicode padrão em 🐪" você pode obter do que escrevi. Bem, sim, sim: você deveria estar usando Unicode::CollateeUnicode::LineBreak também. E provavelmente mais.
Como você pode ver, há demasiadas coisas Unicode que você realmente não precisa se preocupar com para lá para sempre existe tal coisa como "padrão para Unicode".
O que você vai descobrir, como fizemos no item 5.8, é simplesmente impossível impor todas essas coisas no código que não foi projetado desde o início para dar conta delas. Seu egoísmo bem intencionado acabou com o mundo inteiro.
E mesmo depois de fazer isso, ainda existem problemas críticos que exigem muita reflexão para serem acertados. Não há opção que você possa ativar. Nada além de cérebro, e eu quero dizer cérebro real , será suficiente aqui. Há muitas coisas que você precisa aprender. Além do retiro para a máquina de escrever manual, você simplesmente não pode esperar passar despercebido. Este é o século XXI e você não pode desejar que o Unicode se afaste por ignorância voluntária.
Você tem que aprender. Período. Nunca será tão fácil que "tudo funcione", porque isso garantirá que muitas coisas não funcionem - o que invalida a suposição de que possa haver uma maneira de "fazer tudo funcionar".
Você pode conseguir alguns padrões razoáveis ​​para poucas e muito limitadas operações, mas não sem pensar muito mais nas coisas do que eu acho que você tem.
Como apenas um exemplo, a ordem canônica vai causar algumas dores de cabeça reais. 😭 "\x{F5}" 'õ' , "o\x{303}" 'õ' , "o\x{303}\x{304}" 'ȭ' e"o\x{304}\x{303}" 'ō̃' devem corresponder a 'õ' , mas como no mundo você fará isso? Isso é mais difícil do que parece, mas é algo que você precisa levar em consideração. 💣
Se há uma coisa que eu sei sobre Perl, é o que seus bits Unicode fazem e não fazem, e prometo a você: "̲ᴛ̲ʜ̲ᴇ̲ʀ̲ᴇ̲ ̲ᴛ̲ʜ̲ᴇ̲ʀ̲ᴇ̲s̲ɪ̲ ̲ɴ̲ᴏ̲ ̲U̲ɴ̲ɪ̲ᴄ̲ᴏ̲ᴅ̲ᴇ̲ ̲ᴍ̲ᴀ̲ɢ̲ɪ̲ᴄ̲ ̲ʙ̲ᴜ̲ʟ̲ʟ̲ᴇ̲ᴛ̲ ̲" 😞
Você não pode simplesmente alterar alguns padrões e obter uma navegação suave. É verdade que eu corro 🐪 com PERL_UNICODEdefinido como"SA" , mas isso é tudo, e mesmo isso é principalmente para coisas de linha de comando. Para um trabalho real, eu passo por todas as etapas descritas acima e faço muito, muito, muito cuidadosamente.
Əɥ ¡ƨdləɥ ƨᴉɥʇ ədoɥ puɐ ʻλɐp əɔᴉu ɐ ʞɔnl poo⅁.
Como Sherm Pendley apontou: "Todos!". Se eu escrever hoje algo novo, o UTF-8 deve ser a maneira mais fácil de fazer as coisas. Não é. Seu clichê prova isso. Nem todo mundo tem esse conhecimento para transformar tantos copos em posições corretas. Me desculpe, eu tive um dia longo e difícil, então vou comentar na entrada principal amanhã mais com exemplos.
Uma conclusão deve ser óbvia ao ler a lista acima: Não dobre caso. Apenas não. Sempre. Computacionalmente caro e com semântica que depende crucialmente do que quer que seja que "localidade" tente identificar sem êxito.
Eu sou o único que acha irônico que este post do tchrist seja tão diferente no FF / Chrome / IE / Opera, em algum momento até o ponto da ilegibilidade?
— Daneboy
Embora eu geralmente goste do post e tenha votado positivamente, uma coisa me incomoda muito. Há muitos "códigos que ... estão quebrados". Embora eu não discuta com a afirmação, acho que seria bom mostrar a fragilidade. Dessa maneira, ele passaria (essa parte da resposta) de um discurso retórico para a educação.
@xenoterracide Não, eu não usei pontos de código intencionalmente problemáticos; é uma trama para você instalar a incrível fonte Symbola de George Douros , que abrange o Unicode 6.0. De @depesz Não há espaço aqui para explicar por que cada suposição está errada. @leonbloy Muita coisa se aplica ao Unicode em geral, não apenas ao Perl. Parte desse material pode aparecer em 🐪 Programming Perl 🐪, 4ª edição , com lançamento em outubro. Ainda tenho um mês para trabalhar nele e o Unicode está lá;
— Regexes
Há dois estágios no processamento de texto Unicode. O primeiro é "como posso inseri-lo e produzi-lo sem perder informações". O segundo é "como trato o texto de acordo com as convenções do idioma local".
O post de tchrist cobre ambos, mas a segunda parte é de onde vêm 99% do texto em seu post. A maioria dos programas nem lida com E / S corretamente, por isso é importante entender isso antes mesmo de você começar a se preocupar com normalização e agrupamento.
Este post tem como objetivo resolver esse primeiro problema
Quando você lê dados no Perl, não se importa com a codificação. Ele aloca um pouco de memória e armazena os bytes por lá. Se você disser print $str, ele apenas divide esses bytes no seu terminal, que provavelmente está configurado para assumir que tudo o que está escrito nele é UTF-8, e seu texto é exibido.
Exceto, não é. Se você tentar tratar os dados como texto, verá que Algo Ruim está acontecendo. Você não precisa ir além de lengthver que o que Perl pensa sobre sua string e o que você pensa sobre sua string discorda. Escreva uma linha como: perl -E 'while(<>){ chomp; say length }'e digite文字化け e você obtém 12 ... não a resposta correta, 4.
Isso ocorre porque o Perl assume que sua string não é texto. Você precisa dizer que é um texto antes de fornecer a resposta certa.
Isso é fácil; o módulo Encode tem as funções para fazer isso. O ponto de entrada genérico é Encode::decode(ouuse Encode qw(decode) , é claro). Essa função pega alguma string do mundo exterior (o que chamaremos de "octetos", uma maneira extravagante de dizer "bytes de 8 bits"), e a transforma em algum texto que o Perl entenderá. O primeiro argumento é um nome de codificação de caracteres, como "UTF-8" ou "ASCII" ou "EUC-JP". O segundo argumento é a string. O valor de retorno é o escalar Perl que contém o texto.
(Também existe Encode::decode_utf8, que assume UTF-8 para a codificação.)
Se reescrevermos uma linha:
Digitamos 文字 化 け e obtemos "4" como resultado. Sucesso.
Essa é a solução para 99% dos problemas de Unicode no Perl.
A chave é que, sempre que houver texto no seu programa, você deve decodificá-lo. A Internet não pode transmitir caracteres. Os arquivos não podem armazenar caracteres. Não há caracteres no seu banco de dados. Existem apenas octetos, e você não pode tratar octetos como caracteres no Perl. Você deve decodificar os octetos codificados em caracteres Perl com o módulo Encode.
A outra metade do problema é obter dados do seu programa. Isso é fácil; você acabou de use Encode qw(encode)decidir qual será a codificação dos seus dados (UTF-8 para terminais que compreendem UTF-8, UTF-16 para arquivos no Windows etc.) e, em seguida, produza o resultado em encode($encoding, $data)vez de apenas produzir $data.
Essa operação converte os caracteres do Perl, que é o que seu programa opera, em octetos que podem ser usados ​​pelo mundo exterior. Seria muito mais fácil se pudéssemos enviar caracteres pela Internet ou para nossos terminais, mas não podemos: apenas octetos. Portanto, temos que converter caracteres em octetos, caso contrário, os resultados serão indefinidos.
Para resumir: codifique todas as saídas e decodifique todas as entradas.
Agora, falaremos sobre três questões que tornam isso um pouco desafiador. O primeiro são as bibliotecas. Eles lidam com texto corretamente? A resposta é ... eles tentam. Se você baixar uma página da Web, o LWP retornará seu resultado como texto. Se você chamar o método certo para o resultado, isso é (e isso acontece decoded_content, não content, que é apenas o fluxo de octetos obtido do servidor). Os drivers de banco de dados podem ser esquisitos; se você usar DBD :: SQLite com apenas Perl, funcionará, mas se alguma outra ferramenta colocar texto armazenado como alguma codificação diferente de UTF-8 em seu banco de dados ... bem ... não será tratado corretamente até você escrever o código para manipulá-lo corretamente.
A saída de dados geralmente é mais fácil, mas se você vê "caracteres largos impressos", sabe que está atrapalhando a codificação em algum lugar. Esse aviso significa "ei, você está tentando vazar caracteres Perl para o mundo exterior e isso não faz nenhum sentido". Seu programa parece funcionar (porque a outra extremidade geralmente manipula os caracteres Perl brutos corretamente), mas está muito danificado e pode parar de funcionar a qualquer momento. Corrija-o com um explícito Encode::encode!
O segundo problema é o código-fonte codificado em UTF-8. A menos que você diga use utf8na parte superior de cada arquivo, o Perl não assumirá que seu código-fonte é UTF-8. Isso significa que, toda vez que você diz algo do tipo my $var = 'ほげ', está injetando lixo em seu programa, que quebrará tudo horrivelmente. Você não precisa "usar utf8", mas se não o fizer, não deverá usar caracteres não ASCII no seu programa.
O terceiro problema é como o Perl lida com o passado. Há muito tempo, não existia o Unicode, e Perl presumiu que tudo era um texto em latim 1 ou binário. Portanto, quando os dados entram no seu programa e você começa a tratá-los como texto, o Perl trata cada octeto como um caractere latino-1. É por isso que, quando solicitamos o tamanho de "文字 化 we", obtemos 12. Perl presumiu que estávamos operando na string Latin-1 "æååã" (que tem 12 caracteres, alguns dos quais não são impressos).
Isso é chamado de "atualização implícita", e é uma coisa perfeitamente razoável de se fazer, mas não é o que você deseja se o seu texto não for latino-1. É por isso que é fundamental decodificar explicitamente a entrada: se você não fizer isso, o Perl o fará, e isso pode ser errado.
As pessoas enfrentam problemas onde metade dos dados é uma sequência de caracteres adequada e alguns ainda são binários. O Perl interpreta a parte que ainda é binária como se fosse um texto em latim-1 e depois a combina com os dados corretos dos caracteres. Isso fará com que pareça que o manuseio correto de seus personagens interrompeu seu programa, mas, na realidade, você simplesmente não o corrigiu o suficiente.
Aqui está um exemplo: você tem um programa que lê um arquivo de texto codificado em UTF-8, adere um Unicode PILE OF POOa cada linha e o imprime. Você escreve assim:
E, em seguida, execute alguns dados codificados em UTF-8, como:
Ele imprime os dados UTF-8 com um cocô no final de cada linha. Perfeito, meu programa funciona!
Mas não, você está apenas fazendo concatenação binária. Você está lendo octetos do arquivo, removendo um \ncom chomp e, em seguida, inserindo os bytes na representação UTF-8 do PILE OF POOpersonagem. Ao revisar seu programa para decodificar os dados do arquivo e codificar a saída, você notará que obtém lixo ("ð ©") em vez de cocô. Isso levará você a acreditar que decodificar o arquivo de entrada é a coisa errada a se fazer. Não é.
O problema é que o cocô está sendo implicitamente atualizado como latin-1. Se você use utf8criar o texto literal em vez de binário, ele funcionará novamente!
(Esse é o problema número um que eu vejo ao ajudar as pessoas com Unicode. Eles fizeram a parte certa e isso interrompeu o programa. O que é triste com resultados indefinidos: você pode ter um programa em funcionamento por um longo tempo, mas quando começa a repará-lo, Não se preocupe, se você estiver adicionando instruções de codificação / decodificação ao seu programa e ele quebrar, isso significa apenas que você tem mais trabalho a fazer. Da próxima vez, quando você criar o Unicode em mente desde o início, será muito facil!)
Isso é realmente tudo o que você precisa saber sobre Perl e Unicode. Se você informar ao Perl quais são seus dados, ele possui o melhor suporte Unicode entre todas as linguagens de programação populares. No entanto, se você presumir que ele saberá magicamente que tipo de texto você está alimentando, você irá lixeira irrevogavelmente seus dados. Só porque seu programa funciona hoje em seu terminal UTF-8 não significa que ele funcionará amanhã em um arquivo codificado em UTF-16. Portanto, proteja-o agora e poupe a dor de cabeça de descartar os dados de seus usuários!
A parte fácil de lidar com o Unicode é codificar a saída e decodificar a entrada. A parte difícil é encontrar todas as suas entradas e saídas e determinar qual é a codificação. Mas é por isso que você ganha muito dinheiro :)
O princípio é bem explicado, mas a abordagem prática para E / S está ausente. O uso explícito do Encodemódulo é tedioso e propenso a erros, e torna a leitura do código referente à E / S realmente dolorosa. As camadas de E / S fornecem uma solução à medida que codificam e decodificam de forma transparente, quando necessário. opene binmodepermitir sua especificação, e o pragma opendefine os padrões, como recomenda a tchrist em sua resposta.
Estamos todos de acordo em que é um problema difícil por vários motivos, mas esse é precisamente o motivo de tentar facilitar a todos.
Existe um módulo recente no CPAN, utf8 :: all , que tenta "ativar o Unicode. Tudo isso".
Como foi apontado, você não pode magicamente fazer com que todo o sistema (programas externos, solicitações externas da Web etc.) também usem Unicode, mas podemos trabalhar juntos para facilitar ferramentas sensíveis que facilitam a solução de problemas comuns. Essa é a razão pela qual somos programadores.
Se utf8 :: all não fizer algo que você deveria fazer, vamos aprimorá-lo para torná-lo melhor. Ou vamos criar ferramentas adicionais que, juntas, possam atender às diferentes necessidades das pessoas, da melhor maneira possível.
— Randy Stauner
Vejo muito espaço para melhorias no utf8::allmódulo citado . Foi escrito antes do unicode_stringsrecurso, que Fɪɴᴀʟʟʏ ᴀɴᴅ ᴀᴛ Lᴏɴɢ Lᴀsᴛ corrige regexes para ter um /uneles. Não estou convencido de que isso gera uma exceção nos erros de codificação, e isso é algo que você realmente deve ter. Ele não carrega no use charnames ":full"pragma, que ainda não foi carregado automaticamente. Ele não avisa [a-z]e tal, printflarguras de string, usando em \nvez de \Re em .vez de \X, mas talvez essas sejam mais uma Perl::Criticquestão. Se fosse eu, adicionaria 𝐍𝐅𝐃 dentro e 𝐍𝐅𝐂 fora.
@tchrist O rastreador de problemas para utf8 :: all está aqui. github.com/doherty/utf8-all/issues Eles adorariam ouvir suas sugestões.
— Schwern 12/06
@ Schwern: Sim, mas fique à vontade para furtar e beliscar as coisas que escrevi aqui. Para ser sincero, ainda estou sentindo / aprendendo o que pode ser feito versus o que deve ser feito e onde. Aqui está um bom exemplo off descarregamento de classificação: unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r. Da mesma forma, pequenas etapas de pré-processamento como ... | ucsort --upper --preprocess='s/(\d+)/sprintf "%#012d", $1/ge'essas também podem ser muito boas, e eu não gostaria de tomar decisões de outras pessoas por elas. Ainda estou construindo minha caixa de ferramentas Unicode .
Eu acho que você não entendeu o Unicode e sua relação com o Perl. Não importa como você armazena dados, Unicode, ISO-8859-1 ou muitas outras coisas, seu programa precisa saber como interpretar os bytes que recebe como entrada (decodificação) e como representar as informações que deseja gerar (codificação ) Entenda errado essa interpretação e você confunde os dados. Não há nenhuma configuração mágica padrão dentro do seu programa que diga o que está fora do programa como agir.
Você acha que é difícil, provavelmente, porque você está acostumado a tudo ser ASCII. Tudo o que você deveria estar pensando era simplesmente ignorado pela linguagem de programação e por todas as coisas com as quais tinha que interagir. Se tudo não usasse nada além de UTF-8 e você não tivesse escolha, o UTF-8 seria igualmente fácil. Mas nem tudo usa UTF-8. Por exemplo, você não quer que seu identificador de entrada pense que está obtendo octetos UTF-8, a menos que seja realmente, e não deseja que seus identificadores de saída sejam UTF-8 se a coisa que ler neles puder lidar com UTF-8 . Perl não tem como saber essas coisas. É por isso que você é o programador.
Eu não acho que Unicode no Perl 5 é muito complicado. Eu acho assustador e as pessoas evitam. Há uma diferença. Para esse fim, coloquei Unicode no Learning Perl, 6ª Edição , e há muitas coisas Unicode na Effective Perl Programming . Você precisa gastar tempo para aprender e entender o Unicode e como ele funciona. Você não será capaz de usá-lo efetivamente de outra forma.
Eu acho que você tem razão: é assustador. Deveria ser? Para mim é uma bênção Unicode, usá-lo no Perl5 não é (não presumo que seja ASCII, minha língua materna precisa de pelo menos iso8859-4). Instalei o Rakudo e tudo o que tentei com o UTF-8 (nesta caixa de areia limitada) funcionou imediatamente. Perdi alguma coisa? Enfatizo novamente: é bom ter um suporte Unicode otimizado, mas na maioria das vezes não é necessário. Para afastar o medo do assunto, uma maneira é que todo mundo leia muito para entender os aspectos internos. Outro: temos um pragma especial, para use utf8_everywhereque as pessoas sejam felizes. Por que não o último?
Eu ainda acho que você está perdendo o objetivo. O que funcionou? Você não precisa entender internals. Você precisa entender os aspectos externos e como deseja lidar com cadeias de caracteres que tenham codificações diferentes e representações diferentes dos mesmos caracteres. Leia o conselho de Tom novamente. A maior parte do que ele diz, aposto que você descobrirá que Rakudo não lida com você.
— Brian d foy #
@wk: Leia a resposta de Randy novamente. Ele já lhe disse quais são as limitações.
@ brian d foy: acho que essas limitações são boas, como diz tchrist, não existe uma bala mágica para todos os aspectos (admito: não vi a maioria deles antes de fazer essa pergunta aqui). Portanto, quando abordamos muitas coisas básicas com algo como utf8 :: all, não é necessário que todos construam seu próprio imenso padrão, apenas para que noções básicas sobre o manuseio do utf8 funcionem. Com "sem medo nenhum", quero dizer: todos podem iniciar seus projetos sabendo que o básico está coberto. Sim, você está certo, ainda há muitos problemas. Mas quando começar é mais fácil, teremos mais pessoas envolvidas na solução delas. IMHO
@wk - o único "errado" com o "utf8: all" ou "uni :: perl é apenas um - eles não estão no CORE - então todos devem instalá-lo a partir do CPAN. E se você acha que esse não é um grande problema lidar - repensar favor - sim, é mais fácil utf8 utilização com um módulo auxiliar Sem ele, o perl NÚCLEO ainda tem suporte a Unicode -.. mas muito-muito complicado e isso é errado.
Ao ler este tópico, muitas vezes tenho a impressão de que as pessoas estão usando " UTF-8 " como sinônimo de " Unicode ". Faça uma distinção entre os "Pontos de código" do Unicode, que são um parente ampliado do código ASCII e as várias "codificações" do Unicode. E existem alguns deles, dos quais UTF-8, UTF-16 e UTF-32 são os atuais e outros mais são obsoletos.
Por favor, UTF-8 (assim como todas as outras codificações ) existe e tem significado apenas na entrada ou na saída. Internamente, desde o Perl 5.8.1, todas as strings são mantidas como "pontos de código" Unicode. É verdade que você precisa habilitar alguns recursos, como admiravelmente abordados anteriormente.
— MeirG
Concordo que as pessoas frequentemente confundem Uɴɪᴄᴏᴅᴇ com UTF-8⧸16⧸32, mas não é fundamental e criticamente verdade que Uɴɪᴄᴏᴅᴇ seja apenas um conjunto de caracteres ampliado em relação a ᴀsᴄɪɪ. No máximo, isso não passa de mero número 10646 . Uɴɪᴄᴏᴅᴇ inclui muito mais : regras para agrupamento, dobra de caixa, formas de normalização, clusters de grafema, quebra de palavras e linhas, scripts, equações numéricas, larguras, bidirecionalidade, variantes de glifos, comportamento contextual, localidades, regexes, classes combinadas, centenas de propriedades e muito mais t
@ tchrist: o primeiro passo é colocar os dados no seu programa e sair para o mundo exterior sem destruí-lo. então você pode se preocupar com agrupamentos, dobragem de caixas, variantes de glifos, etc. etapas do bebê.
Eu concordo, conseguir que o perl não jogue lixo na entrada ou na saída deve ser a primeira prioridade. O que eu gostaria era de ter um módulo ou pragma que pudesse incorporar a seguinte conversa fictícia: "- Prezado Perl. Para este programa, todas as entradas e saídas serão exclusivamente de UTF-8. Por favor, não descarte meus dados? - Então, apenas você diz UFT-8. Tem certeza? - Sim. - Sério, realmente tem certeza? - Absolutamente. - E você aceita que eu possa me comportar de maneira estranha se receber dados que não sejam da UTF-8? - Sim, tudo bem. - OK então."
— Hjdaldal
Existe uma quantidade realmente horrível de código antigo por aí, em grande parte, na forma de módulos CPAN comuns. Descobri que tenho que ter bastante cuidado ao ativar o Unicode se usar módulos externos que possam ser afetados por ele e ainda estou tentando identificar e corrigir algumas falhas relacionadas ao Unicode em vários scripts Perl que uso regularmente (em particular, o iTiVo falha mal em qualquer coisa que não seja ASCII de 7 bits devido a problemas de transcodificação).
Eu quis dizer usar a -Copção para garantir que o Perl esteja na mesma página que eu sou Unicode, porque continuo decidindo usar a ISO 8859/1 em vez do Unicode, mesmo que eu esteja explicitamente definindo $LANGe $LC_ALLadequadamente. (Na verdade, isso pode refletir bugs nas bibliotecas de código de idioma da plataforma.) Seja o que for, é altamente irritante que eu não possa usar o iTivo em programas com sotaques, porque os scripts Perl que executam o trabalho ficam com erros de conversão.
Um solitário -Csem opções é com erros e propenso a erros . Você quebra o mundo. Defina o PERL5OPTenvariável como -Ce você verá o que quero dizer. Tentamos dessa maneira na v5.8 e foi um desastre. Você simplesmente não pode nem deve dizer aos programas que não esperam que agora estejam lidando com o Unicode, gostem ou não. Há também problemas de segurança. No mínimo, tudo o que fizer print while <>será interrompido se passar dados binários. O mesmo acontece com todo o código do banco de dados. Esta é uma péssima ideia.
— Tchrist 28/05
Eu estava falando genericamente, na verdade, não especificamente -Csem opções. A invocação específica com a qual eu estava trabalhando era -CSDA. Dito isto, fiquei preso com o 5.8.x por um longo tempo (olá MacPorts ...), então talvez isso tenha sido parte disso.
— Geekosaur 28/05
Eu corro com PERL_UNICODE definido como SA. Você NÃO PODE configurá-lo para D.
@ tchrist: Alguns Perl varmint publicaram código mostrando o uso de -CSDA e PERL_UNICODE = SDA . Por favor, use sua influência na comunidade. Ele deve ser parado!
— 21712 Ashley
Você deve ativar o recurso de strings unicode, e esse é o padrão se você usar a v5.14;
Você realmente não deve usar identificadores unicode esp. para código estrangeiro via utf8, pois eles são inseguros no perl5, apenas o cperl acertou. Veja, por exemplo, http://perl11.org/blog/unicode-identifiers.html
Em relação ao utf8 para seus manipuladores de arquivos / fluxos: você precisa decidir por si mesmo a codificação de seus dados externos. Uma biblioteca não pode saber disso, e como nem a libc suporta utf8, dados utf8 adequados são raros. Há mais wtf8, a aberração de janelas do utf8 ao redor.
BTW: Moose não é realmente "Modern Perl", eles apenas sequestraram o nome. Moose é perfeito perl pós-moderno no estilo Larry Wall misturado com o estilo Bjarne Stroustrup, com uma aberração eclética da sintaxe perl6 adequada, por exemplo, usando strings para nomes de variáveis, sintaxe de campos horríveis e uma implementação ingênua e imatura que é 10x mais lenta que uma implementação adequada. cperl e perl6 são os verdadeiros perls modernos, em que a forma segue a função e a implementação é reduzida e otimizada.