GNU/Linux >> Linux Esercitazione >  >> Linux

Utilizzo di Uniq su testo Unicode?

Voglio rimuovere le righe duplicate da un file con parole di script siriano. Il file sorgente ha 3 righe, la prima e la terza sono identiche.

$ cat file.txt 
ܐܒܘܢ
ܢܗܘܐ
ܐܒܘܢ

Quando uso sort e uniq , il risultato presume che tutte e 3 le righe siano identiche, il che è sbagliato:

$ cat file.txt | sort | uniq -c
      3 ܐܒܘܢ

Anche l'impostazione esplicita della localizzazione su Syriac non aiuta.

$ LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c      
     3 ܐܒܘܢ

Perché dovrebbe succedere?
Sto usando Kubuntu 18 e bash, se è importante.

Risposta accettata:

L'implementazione GNU di uniq come si trova su Ubuntu, con -c , non riporta i conteggi di identici contigui righe ma conteggi di righe contigue che ordinano lo stesso¹.

La maggior parte delle localizzazioni internazionali sui sistemi GNU ha quel bug che molti caratteri completamente non correlati sono stati definiti con lo stesso ordinamento, la maggior parte di essi perché il loro ordinamento non è affatto definito. La maggior parte degli altri sistemi operativi si assicura che tutti i caratteri abbiano un ordine di ordinamento diverso.

$ expr ܐ = ܒ
1

(expr 's = operatore, per argomenti che non sono numerici, restituisce 1 se gli operandi ordinano allo stesso modo, 0 altrimenti).

È lo stesso con ar_SY.UTF-8 o en_GB.UTF-8 .

Ciò di cui avresti bisogno è un locale in cui a quei personaggi sia stato assegnato un ordine di ordinamento diverso. Se Ubuntu avesse le impostazioni locali per la lingua siriana, potresti aspettarti che a quei caratteri sia stato assegnato un ordine di ordinamento diverso, ma Ubuntu non ha tali impostazioni locali.

Puoi guardare l'output di locale -a per un elenco delle localizzazioni supportate. Puoi abilitare più locali eseguendo dpkg-reconfigure locales come root . Puoi anche definire più locali manualmente usando localedef in base ai file di definizione in /usr/share/i18n/locales , ma lì non troverai dati per la lingua siriaca.

Nota che in:

LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c

Stai solo impostando la variabile LC_COLLATE per il cat comando (che non influisce sul modo in cui restituisce il contenuto del file, cat non si preoccupa delle regole di confronto e nemmeno della codifica dei caratteri in quanto non è un'utilità di testo). Vorresti impostarlo per entrambi sort e uniq . Vorresti anche impostare LC_CTYPE a una locale che ha un set di caratteri UTF-8.

Poiché il tuo sistema non ha syr_SY.utf8 locale, è lo stesso che usare il C locale (il locale predefinito).

In realtà, qui il locale C o C.UTF-8 è probabilmente il locale che vorresti usare.

In quelle impostazioni locali, l'ordine di confronto si basa sul punto di codice, punto di codice Unicode per C.UTF-8, valore di byte per C, ma finisce per essere lo stesso della codifica dei caratteri UTF-8 che ha quella proprietà.

$ LC_ALL=C expr ܐ = ܒ
0
$ LC_ALL=C.UTF-8 expr ܐ = ܒ
0

Quindi con:

(export LANG=ar_SY.UTF-8 LC_COLLATE=C.UTF-8 LANGUAGE=syr:ar:en
 unset LC_ALL
 sort <file | uniq -c)

Avresti un LC_CTYPE con UTF-8 come set di caratteri, un ordine di confronto basato sul punto di codice e le altre impostazioni rilevanti per la tua regione, quindi ad esempio messaggi di errore in siriaco o arabo se GNU coreutils sort o uniq i messaggi erano stati tradotti in quelle lingue (non l'hanno ancora fatto).

Correlati:come contrassegnare più contatti per inviare lo stesso testo di ccn - funzione che esiste su Android?

Se non ti interessano quegli altri impostazioni, è altrettanto facile (e anche più portatile) da usare:

<file LC_ALL=C sort | LC_ALL=C uniq -c

Oppure

(export LC_ALL=C; <file sort | uniq -c)

come ha già mostrato @isaac.


Linux
  1. Crea file utilizzando la riga di comando in Linux

  2. Ordinamento di un file delimitato da tabulazioni

  3. Come generare un elenco di righe univoche nel file di testo utilizzando uno script di shell Linux?

  4. Utilizzo di nc per trasferire file di grandi dimensioni

  5. Ottieni una riga specifica dal file di testo usando solo lo script della shell

Utilizzo del file di configurazione SSH

Come bloccare un file di testo in Linux usando il comando flock

Procedura:un'introduzione all'uso di Git

Trasferisci file usando WinSCP

Trova e sostituisci il testo in un file tra un intervallo di righe usando sed

Come inserisco il testo nella prima riga di un file usando sed?