Extrai apenas caracteres chineses

6

Estou trabalhando em um texto escrito em italiano e chinês e preciso extrair apenas caracteres chineses usando AWK . Como posso fazer isso?

Eu tentei:

[O intervalo de caracteres chineses do Unicode é 4E00 thru 9FFF (344 270 200 thru 351 277 277) , portanto, o teste deve ser >"3" and <"2" (para evitar pegar 4 códigos char UTF-8)]:

{
f=0;
for ( i=1; i<=length; i++)
if(substr($0, i, 1)>"3" &&substr($0, i, 1)<"2")
f = 1 

print $f
}

Mas há um erro ou mais erros. Não consigo encontrá-los

    
por ettore 26.06.2015 / 12:12

2 respostas

13

Seu problema é que ao filtrar bytes brutos em um fluxo de caracteres UTF-8, você está comendo parte de uma sequência unicode em um arquivo UTF-8, resultando em uma seqüência de bytes inválida. Isso não pode funcionar. Em vez disso, você precisa usar uma ferramenta que entenda o UTF-8 e aplicar um filtro nos dados unicode, em vez dos bytes brutos.

Como não sei qual implementação de awk você está usando, é impossível dizer se ela suporta unicode. No entanto, sei que o perl é totalmente seguro para unicode, portanto, o seguinte perl one-liner deve funcionar:

perl -CS -p -e 's/[^\s\p{Han}]//g'

O \s é para espaço em branco, o que eu suponho que você queira ver. O \p{Han} bit informa ao perl que queremos corresponder caracteres declarados em Unicode como sendo usados no script Han (ou seja, caracteres chineses). Não sei se você precisa de algum caractere de pontuação que não esteja incluído nesse intervalo; se você fizer isso, você pode precisar adicionar isso também.

Em seguida, negamos o intervalo com ^ no início e, finalmente, o codificamos em um comando substituto global ( s///g ), onde dizemos ao perl para substituir instâncias da peça após a primeira barra (nosso intervalo negado, ou, "tudo não neste intervalo") com a parte depois do segundo e antes do terceiro (isto é, nada).

Se você não precisa incluir vários intervalos, é possível descartar a construção [^] e alternar para usar \P em vez de \p , o que faz a mesma inversão de correspondência.

O que resta são os intervalos de caracteres que inserimos - caracteres unicode no script Han, além do espaço em branco.

Para obter mais informações, consulte perldoc perlre para obter uma explicação sobre como o perl lida com expressões regulares e perldoc perluniprops para uma lista de possíveis propriedades unicode (os bits que você pode colocar dentro de uma construção \p{} ou \P{} ). / p>     

por 26.06.2015 / 14:25
1

Usando awk , você pode fazer isso como:

awk '{for(i=1; i<=length;i++) if(substr($0,i,1)>="\xS_INDEX" && substr($0,i,1)<="\xE_INDEX"){printf substr($0,i,1);f=1;} if(f)printf "\n"; f=0}' filename

Aqui S_INDEX e E_INDEX são os índices inicial e final de ascii em hex .

Para entrada:

1243
135
dgfsdaa
125
sdg124
sdf34

Selecionando apenas dígitos: S_INDEX = 30 e E_INDEX = 39

Saída:

1243
135
125
124
34
    
por 26.06.2015 / 12:48