Bilinmeyen unicode karakteri text dosyalarından kaldırma - sed, diğer bash / shell yöntemleri


9

Arama ve aynı ada sahip bazı dosyalarda bilinmeyen bir karakterin tüm oluşumları değiştirmek gerekir.

Bu tür dosyaları vi ile açarak, o karakter için <91> kodunu okudum. Onları nano ile açarak, bir elmasta (siyah rumble) bir "soru işareti" okudum.

Bu bilinmeyen karakteri bir alıntı ile değiştirmek istiyorum ('). Ben şanssız birçok yolu deniyorum.

Denedim:

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



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

EDIT Karakter hakkında daha fazla bilgi:

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

Eğer daha fazlasına ihtiyacın varsa sor!


Hangi yolla yapar sed -i "s/\x91/'/g"bu konuda filedeğil işin?
Stéphane Chazelas

Yanıtlar:


3

Kullanarak bir göz atmanız hexdump -Cve çevresindeki baytları bulmanız gerekir. UTF-8, neyi varsayarsak violarak gösterir <91>(metinde unicode noktası anlamsız ondalık 145) iki bayt, 0xC2 ve 0x91 olacaktır.

Değişikliklerinizin işe yaramadığı anlamına gelir, ancak yaptığınız şey 0x91 yerine 0x27'yi değiştirdiyseniz, UTF-8'i geçersiz kılmış olursunuz (iki baytlık bir dizinin ikinci baytı her zaman yüksek bit kümesine sahiptir, yani > = 0x80). Bu, analizinizi zorlaştırabilir, ancak vidaha sonra bunu göstermelidir ?'.

Bununla birlikte, bunu test ettim ve işe yarıyor:

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

Eğer $ARGV[0]zaman var <>başvurulmaktadır, perl argüman yığını kapalı bu çıkar ve giriş için kullanılmak üzere bir filepath olarak alır (ı ile kısa komut çimdik daha kolay ve iş bulmak biri gömlekleri, BTW yerine). Bu bellekte birikir (dosyalar çok büyük olmadığı sürece iyidir), perl -iyerinde düzenleme yarış koşullarından kaçınmak için orijinal dosyayı yeniden adlandırır (bkz. perldoc perlrun).

Yani bunu kullanabilirsiniz:

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

çalışmıyor, soru işareti kalıyor ...
jasmines

hexdump -COrada gerçekten ne olduğunu görmek için kontrol ettin mi?
goldilocks

3

Gerçekten de 0x + baytı değil, U + 0091 (UTF-8 kodlamasında 0xc2 0x91) karakteri ise:

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

Dönüştürür '.

GNU ile sed:

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

Düzenle:

Ancak, sizin durumunuzda, dosya UTF-8'de değildir. UTF-8 karakterleri, yalnızca ASCII karakterleri için bir bayttır (0 - 0x7F değerleri için). Diğer karakterler, değeri büyük olan iki veya daha fazla bayt ile temsil edilir 0x7F. Bu nedenle 0x91, etrafında 0x7F'den daha büyük baytı olmayan bir bayt bir utf-8 dosyasında bulunamaz.

Büyük olasılıkla, dosyanız tek baytlık bir karakter kümesinde, büyük olasılıkla Windows-1252 gibi bazı Microsoft .

Windows-1252'de, 0x91 sol tek tırnak işaretidir. Unicode eşdeğeri UTF-8'de yazılan U + 2018'dir 0xe2 0x80 0x98.

Dosyanızı UTF-8'e dönüştürmek istiyorsanız, en iyisi muhtemelen bunun için özel bir araç kullanmaktır. Sevmek:

recode windows-1252..utf8 < file

Veya:

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

Veya her biri için yapmak istiyorsanız 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 {} +

çalışmıyor, soru işareti kalıyor ...
jasmines

@jasmines O zaman a değil U+0091. Lütfen LC_ALL=C sed -n l < filesorunun çıktısını ekleyin .
Stéphane Chazelas

\ 221 gibi görünüyor
jasmines

Dönüştüremiyorum çünkü tek bir dosya değil ... Toplu olarak ve yinelemeli arama ve değiştirme gerekir.
jasmines
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.