2017-02-16 18 views
0

У меня есть файл данных UTF-8 с некоторой неожиданной последовательностью символов UTF-8, которая прерывает обработку данных. Мне нужно заменить эту последовательность с пробелами или любым безопасным характером (Данные из внешнего источника):Bash: Заменить специальную последовательность символов

In Hex: E2 80 8B (​) 

В Баше скрипте, как я могу заменить эти символы с помощью инструмента командной строки, как sed или replace команд? Я пробовал с:

sed 's/​/ /g' file_1 > file_2 

Но он не работает (данные не заменены). Есть ли специальный синтаксис для указания регулярного выражения с символами «hex» вместо символов ascii? Можно заменить «двоичную» замену, используя 3-байтную последовательность?

Примечание: файл UTF-8 кодируются, так что я думаю, что проблема поиска реальной последовательности, потому что не в UTF-8 (3 байта ASCII)

+0

Можете ли вы попытаться объяснить, как эта последовательность байтов «плохой UTF-8»? И не использовать слово «ascii»? –

+0

Это плохо для меня, я предпочитаю использовать «неожиданный». Процесс преобразования удаляет символ. –

+0

Я искал и нашел «Hex String Replacement Using sed» http://stackoverflow.com/questions/7760717/hex-string-replacement-using-sed и попытался использовать последовательность '' s/\ xE2 \ x80 \ x8B// g'', и кажется, что он работает. –

ответ

1

Если действительно байты 0xE2, 0x80 и 0x8B, и это UTF-8 закодированный текст.

Тогда it means:

U+200B ​ e2 80 8b ZERO WIDTH SPACE 

, который используется, чтобы держать слова вместе в какой-нибудь текст.
и которые могут быть напечатаны в Баш как:

$ printf 'zero width\U200Bspace \n' 
zero widthspace 

$ printf 'zero width\U200Bspace \n' | xxd 
00000000: 7a65 726f 2077 6964 7468 e280 8b73 7061 zero width...spa 
00000010: 6365 200a 

И вы можете удалить; поскольку sed фактически понимает байты (а не символы); с:

$ printf 'zero width\U200bspace\n' | sed 's/\xE2\x80\x8B/ /g' 
zero width space 
+0

Спасибо за эту информацию, не знаю о ее существовании. Я могу решить проблему замены (это пространство важно в приложении) с шестнадцатеричным поиском, как в вашем примере. –

0

У меня есть функция PHP для фильтрации таких символов , Это не совсем то, что вы хотите, но все же его можно запустить в консоли, просто установите PHP. Замените in.txt с именем входного файла, out.txt с именем выходного файла и скриптом запуска (php script_file.php). Надеюсь, это будет полезно.

<?php 
const INPUT_FILE_NAME = 'in.txt'; 
const OUTPUT_FILE_NAME = 'out.txt'; 

$finput = fopen(INPUT_FILE_NAME, 'r'); 
$foutput = fopen(OUTPUT_FILE_NAME, 'w'); 

while(! feof($finput)) { 
    $data = fgets($finput); 
    fputs($foutput, strip_bad_utf8($data)); 
} 

fclose($finput); 
fclose($foutput); 

function strip_bad_utf8($str) 
{ 
    $str = sprintf(' %s ', $str); 
    $ret = ''; 
    for ($i = 0;$i < strlen($str);) { 
     $tmp = $str{$i++}; 
     $ch = ord($tmp); 
     if ($ch > 0x7F) { 
      if ($ch < 0xC0) continue; 
      elseif ($ch < 0xE0) $di = 1; 
      elseif ($ch < 0xF0) $di = 2; 
      elseif ($ch < 0xF8) $di = 3; 
      elseif ($ch < 0xFC) $di = 4; 
      elseif ($ch < 0xFE) $di = 5; 
      else continue; 

      for ($j = 0;$j < $di;$j++) { 
       $tmp .= $ch = $str{$i + $j}; 
       $ch = ord($ch); 
       if ($ch < 0x80 || $ch > 0xBF) continue 2; 
      } 
      $i += $di; 
     } 
     $ret .= $tmp; 
    } 
    return $ret; 
} 
?> 

Вот еще две функции для зачистки 3 & 4 байта символов UTF:

function strip_3bytes_utf($text) 
{ 
    return preg_replace("#([\xE0-\xEF][\x80-\xBF]{2})#i", '', $text); 
} 
function strip_4bytes_utf($text) 
{ 
    return preg_replace("#([\xF0-\xF7]{1}[\x80-\xBF]{3})#i", '', $text); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^