Supprimer le caractère Unicode inconnu des fichiers texte - sed, autres méthodes bash / shell


9

J'ai besoin de rechercher et de remplacer toutes les occurrences d'un caractère inconnu dans certains fichiers portant le même nom.

En ouvrant de tels fichiers avec vi, j'ai lu le code <91> pour ce personnage. En les ouvrant avec du nano, j'ai lu un "point d'interrogation" dans un diamant (rhumble noir).

Je voudrais remplacer ce caractère inconnu par une citation ('). J'essaie de nombreuses façons sans chance.

J'ai essayé:

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



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

EDITER Plus d'informations sur le personnage:

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

Si vous avez besoin de plus, demandez!


De quelle manière sed -i "s/\x91/'/g"cela filene fonctionne-t-il pas?
Stéphane Chazelas

Réponses:


3

Vous devriez jeter un œil à l'aide hexdump -Cet trouver les octets autour. En supposant UTF-8, ce qui viapparaît comme <91>(décimal 145, un point unicode dénué de sens dans le texte) serait deux octets, 0xc2 et 0x91.

Cela implique que vos substitutions n'ont pas fonctionné du tout, mais si vous avez simplement remplacé 0x91 par 0x27, vous aurez invalidé l'UTF-8 (le deuxième octet d'une séquence de deux octets a toujours le bit élevé défini, c'est-à-dire est > = 0x80). Cela pourrait compliquer votre analyse, mais videvrait alors l'indiquer ?'.

Cela dit, j'ai testé cela et cela fonctionne:

#!/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;  

Si $ARGV[0]existe quand <>est référencé, perl le supprime de la pile d'arguments et le prend comme chemin de fichier à utiliser pour la saisie (je trouve les scripts courts plus faciles à modifier et à travailler avec plus d'un liners, BTW). Cela s'accumule dans la mémoire (très bien tant que les fichiers ne sont pas massifs), tandis que perl -irenommer le fichier d'origine pour éviter les conditions de concurrence de modification sur place (voir perldoc perlrun).

Vous pouvez donc utiliser cela:

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

ça ne marche pas, le point d'interrogation reste ...
jasmines

L'avez-vous vérifié hexdump -Cpour voir ce qui s'y trouve réellement?
goldilocks

3

Si c'est bien le caractère U + 0091 (0xc2 0x91 dans le codage UTF-8) et non l'octet 0x91, alors:

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

Le convertirait en '.

Avec GNU sed:

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

Éditer:

Cependant, dans votre cas, le fichier n'est pas en UTF-8. Les caractères UTF-8 sont d'un octet, uniquement pour les caractères ASCII (pour les valeurs 0 à 0x7F). Les autres caractères sont représentés par deux octets ou plus dont la valeur est supérieure à 0x7F. Ainsi, un 0x91octet, sans octet supérieur à 0x7F autour, ne peut pas être trouvé dans un fichier utf-8.

Plus probablement, votre fichier est dans un jeu de caractères à un octet, très probablement un Microsoft comme Windows-1252 .

Dans windows-1252, 0x91 est le caractère de guillemet simple gauche. L'équivalent unicode est U + 2018 qui est écrit en UTF-8 0xe2 0x80 0x98.

Si vous souhaitez convertir votre fichier en UTF-8, le mieux est probablement d'utiliser un outil dédié pour cela. Comme:

recode windows-1252..utf8 < file

Ou:

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

Ou si vous voulez le faire pour tous 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 {} +

ça ne marche pas, le point d'interrogation reste ...
jasmines

@jasmines Alors ce n'est pas un U+0091. Veuillez ajouter la sortie de LC_ALL=C sed -n l < fileà la question.
Stéphane Chazelas

il semble être \ 221
jasmines

Je ne peux pas convertir car ce n'est pas un seul fichier ... J'ai besoin de batch et de rechercher et de remplacer récursivement.
jasmines
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.