텍스트 파일에서 알 수없는 유니 코드 문자 제거-sed, 기타 bash / shell 방법


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하지 사용할 수 있습니까?
Stéphane Chazelas

답변:


3

사용 hexdump -C하고 둘러보고 바이트를 찾아야합니다. UTF-8을 가정 vi하면 <91>(십진법 145, 텍스트에서 무의미한 유니 코드 포인트)는 2 바이트 인 0xc2와 0x91입니다.

대체가 전혀 작동하지 않았다는 것을 암시하지만, 0x91을 0x27로 바꾸면 UTF-8이 무효화됩니다 (2 바이트 시퀀스의 두 번째 바이트는 항상 높은 비트 세트를가집니다. > = 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]때 존재 <>참조, 펄이 인수 스택에서이 나타나고 입력을 위해 사용하는 파일 경로로 소요 (나는 짧은 스크립트 조정할 쉽게 직장을 찾아 하나 라이너, BTW 이하). 이것은 메모리에 축적되지만 (파일이 방대하지 않는 한 정밀함), perl -i원본 파일의 이름을 바꾸어 내부 편집 경쟁 조건을 피합니다 (참조 perldoc perlrun).

그래서 당신은 그것을 사용할 수 있습니다 :

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

그것은 작동하지 않습니다, 물음표는 남아 ...
자스민

hexdump -C실제로 무엇이 있는지 확인하기 위해 체크인 했습니까 ?
goldilocks

3

바이트 0x91이 아닌 문자 U + 0091 (UTF-8 인코딩의 0xc2 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까지)의 경우에만 1 바이트입니다. 다른 문자는 값이보다 큰 2 바이트 이상의 바이트로 표시됩니다 0x7F. 따라서 0x910x7F보다 큰 바이트가없는 바이트는 utf-8 파일에서 찾을 수 없습니다.

파일이 단일 바이트 문자 세트 일 가능성이 큽니다. 아마도 windows-1252 와 같은 일부 Microsoft 것 입니다.

windows-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 {} +

그것은 작동하지 않습니다, 물음표는 남아 ...
자스민

@jasmines 그렇다면 그것은 아닙니다 U+0091. 의 결과를 LC_ALL=C sed -n l < file질문에 추가하십시오 .
Stéphane Chazelas

그것은 \ 221 것 같다
재스민

단일 파일이 아니기 때문에 변환 할 수 없습니다 ... 배치 및 재귀 적으로 검색하고 교체해야합니다.
자스민
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.