Rimuovi il carattere unicode sconosciuto dai file di testo - sed, altri metodi bash / shell


9

Ho bisogno di cercare e sostituire tutte le occorrenze di un personaggio sconosciuto in alcuni file con lo stesso nome.

Aprendo questi file con vi, ho letto il codice <91> per quel personaggio. Aprendoli con nano, ho letto un "punto interrogativo" in un diamante (rombo nero).

Vorrei sostituire un personaggio così sconosciuto con una virgoletta ('). Sto provando molti modi senza fortuna.

Provai:

find ./ -name filename.txt -exec perl -i~ -pe "s/\x91/'/" {} \;



find ./ -name filename.txt -exec sed -i "s/\x91/'/g" {} \;

MODIFICA Maggiori informazioni sul personaggio:

Hexadecimal: 91 68 74 74
Decimal: 145 104 116 116
Octal: 221 150 164 164
Binary: 10010001 01101000 01110100 01110100

LC_ALL=C sed -n l < file

\221

Se hai bisogno di altro chiedi!


In che modo lo fa sed -i "s/\x91/'/g"su quella filenon funziona?
Stéphane Chazelas,

Risposte:


3

Dovresti dare un'occhiata usando hexdump -Ce trovare i byte attorno ad esso. Presumendo UTF-8, ciò che viappare come <91>(decimale 145, un punto unicode insignificante nel testo) sarebbe di due byte, 0xc2 e 0x91.

È implicito che le tue sostituzioni non funzionassero affatto, ma se quello che hai fatto è stato solo sostituire 0x91 con 0x27, avrai invalidato l'UTF-8 (il secondo byte di una sequenza a due byte ha sempre il bit alto impostato, cioè è > = 0x80). Questo potrebbe complicare la tua analisi, anche se vidovrebbe quindi mostrarlo come ?'.

Detto questo, l'ho testato e funziona:

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);

my $data = "";
my $file = $ARGV[0];

while (<>) {
    s/\xc2\x91/'/g;
    $data .= $_;
}

open my $out, '>', $file || die "Could not write $file.";
print $out $data;
close $out;  

Se $ARGV[0]esiste quando <>viene referenziato, perl lo estrae dallo stack di argomenti e lo utilizza come percorso file da utilizzare per l'input (trovo che gli script brevi siano più facili da modificare e lavorare con più di una riga, BTW). Questo si accumula in memoria (fino a quando i file non sono enormi), mentre perl -irinomina il file originale per evitare le condizioni di gara sul posto di modifica (vedi perldoc perlrun).

Quindi potresti usare quello:

  find . -name "*.txt" -exec whatever.pl {} +

non funziona, il punto interrogativo rimane ...
gelsomini,

L'hai controllato hexdump -Cper vedere cosa c'è realmente lì?
Riccioli d'oro,

3

Se è effettivamente il carattere U + 0091 (0xc2 0x91 nella codifica UTF-8) e non il byte 0x91, quindi:

PERLIO=:utf8 perl -pi -e "s/\N{U+0091}/'/g" file

Lo convertirebbe in '.

Con GNU sed:

sed -i "s/\xc2\x91/'/" file

Modificare:

Tuttavia, nel tuo caso, il file non è in UTF-8. I caratteri UTF-8 sono un byte, solo per caratteri ASCII (per valori da 0 a 0x7F). Gli altri caratteri sono rappresentati da due o più byte il cui valore è maggiore di 0x7F. Quindi un 0x91byte, con nessun byte maggiore di 0x7F attorno ad esso, non può essere trovato in un file utf-8.

Più probabilmente, il tuo file è in un set di caratteri a byte singolo, molto probabilmente un Microsoft come Windows-1252 .

In windows-1252, 0x91 è il carattere di virgoletta singola sinistra. L'equivalente unicode è U + 2018 che in UTF-8 è scritto 0xe2 0x80 0x98.

Se vuoi convertire il tuo file in UTF-8, probabilmente è meglio usare uno strumento dedicato per quello. Piace:

recode windows-1252..utf8 < file

O:

iconv -f windows-1252 -t utf-8 < file

O se vuoi farlo per ogni filename.txt:

find . -type f -name filename.txt -exec sh -Cc '
  for file do
    mv "$file" "$file~" &&
      iconv -f windows-1252 -t utf-8 < "$file~" > "$file"
  done' sh {} +

non funziona, il punto interrogativo rimane ...
gelsomini,

@jasmines Quindi non è un U+0091. Aggiungi l'output di LC_ALL=C sed -n l < filealla domanda.
Stéphane Chazelas,

sembra essere \ 221
gelsomini il

Non riesco a convertire perché non è un singolo file ... Devo eseguire il batch e cercare ricorsivamente e sostituire.
gelsomini,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.