अज्ञात यूनिकोड चरित्र को टेक्स्टफाइल्स - सेड, अन्य बैश / शेल विधियों से हटा दें


9

मुझे एक अज्ञात चरित्र के सभी आवृत्तियों को खोजने और बदलने की आवश्यकता है, कुछ फ़ाइलों में समान नाम है।

Vi के साथ ऐसी फाइलें खोलते हुए, मैंने उस चरित्र के लिए <91> कोड पढ़ा। नैनो के साथ उन्हें खोलते हुए, मैंने एक हीरे (काले रंबल) में "प्रश्न चिह्न" पढ़ा।

मैं ऐसे अज्ञात चरित्र को एक उद्धरण (') से बदलना चाहूंगा। मैं बिना किस्मत के कई तरीके आजमा रहा हूं।

मैंने कोशिश की:

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



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

चरित्र पर अधिक जानकारी संपादित करें :

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

यदि आपको और अधिक की आवश्यकता है, तो पूछें!


किस तरह sed -i "s/\x91/'/g"से उस पर fileकाम नहीं करता है?
स्टीफन चेजलस

जवाबों:


3

आपको एक नज़र का उपयोग करना चाहिए hexdump -Cऔर इसके चारों ओर बाइट्स ढूंढना चाहिए। UTF-8 को मानते हुए, (दशमलव 145, पाठ में एक यूनिकोड बिंदु) के viरूप में जो दिखाता है , वह <91>दो बाइट्स, 0xc2 और 0x91 होगा।

यह निहित है कि आपके सबस्टेशनों पर काम नहीं किया गया था, लेकिन अगर आपने जो किया था वह केवल 0x27 के साथ 0x27 की जगह था, तो आपने UTF-8 को अमान्य कर दिया होगा (दो बाइट अनुक्रम के दूसरे बाइट में हमेशा उच्च बिट सेट होता है, अर्थात है) > = 0x80)। यह आपके विश्लेषण को जटिल बना सकता है, हालांकि viतब इसे इस रूप में दिखाना चाहिए ?'

उस ने कहा, मैंने यह परीक्षण किया है और यह काम करता है:

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

यदि संदर्भित $ARGV[0]होने पर मौजूद <>है, तो पर्ल इसे तर्क स्टैक से हटाता है और इसे इनपुट के लिए उपयोग करने के लिए एक फ़ाइलपथ के रूप में लेता है (मुझे एक लाइनर, बीटीडब्ल्यू के साथ जुड़ने और काम करने में आसान स्क्रिप्ट मिलती है)। यह मेमोरी में जम जाता है (जब तक कि फाइलें बड़े पैमाने पर नहीं होती हैं), जबकि perl -iएडिट-इन-प्लेस रेस की स्थिति (देखें perldoc perlrun) से बचने के लिए मूल फाइल का नाम बदल देता है ।

तो आप इसका उपयोग कर सकते हैं:

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

यह काम नहीं करता है, सवालिया निशान बना रहता है ...
चमेली

क्या आपने यह देखने के लिए इसकी जाँच की hexdump -Cकि वास्तव में वहाँ क्या है?
गोल्डीलॉक्स

3

यदि यह वास्तव में यूटीएफ -8 एन्कोडिंग में U + 0091 (0xc2 0x91) वर्ण है और बाइट 0x91 नहीं है, तो:

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

इसे रूपांतरित करेगा '

GNU के साथ sed:

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

संपादित करें:

हालाँकि, आपके मामले में, फ़ाइल UTF-8 में नहीं है। UTF-8 वर्ण एक बाइट हैं, केवल ASCII वर्ण (मान 0 से 0x7F के लिए)। अन्य वर्णों को दो या दो से अधिक बाइट्स द्वारा दर्शाया जाता है, जिनका मूल्य इससे अधिक है 0x7F। इसलिए एक 0x91बाइट, जिसके चारों ओर 0x7F से अधिक बाइट नहीं है, वह utf-8 फ़ाइल में नहीं पाया जा सकता है।

अधिक संभावना है, आपकी फ़ाइल एकल-बाइट वर्ण सेट में है, सबसे अधिक संभावना है कि कुछ Microsoft एक जैसे विंडोज़ -1252

विंडोज़ -1252 में, 0x91 बाएँ एकल उद्धरण वर्ण है। यूनिकोड समतुल्य U + 2018 है जो UTF-8 में लिखा गया है 0xe2 0x80 0x98

यदि आप अपनी फ़ाइल को UTF-8 में परिवर्तित करना चाहते हैं, तो संभवतः इसके लिए एक समर्पित टूल का उपयोग करना संभव है। पसंद:

recode windows-1252..utf8 < file

या:

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

या यदि आप इसे प्रत्येक के लिए करना चाहते हैं 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 {} +

यह काम नहीं करता है, सवालिया निशान बना रहता है ...
चमेली

@ चमेली तो यह नहीं है U+0091। कृपया LC_ALL=C sed -n l < fileप्रश्न का आउटपुट जोड़ें ।
स्टीफन चेजलस

यह प्रतीत होता है \ 221
चमेली

मैं कनवर्ट नहीं कर सकता क्योंकि कोई एकल फ़ाइल नहीं है ... मुझे बैच और पुनरावर्ती खोज और प्रतिस्थापित करने की आवश्यकता है।
चमेली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.