Bash:替换特殊字符序列

时间:2017-02-16 13:42:05

标签: regex bash replace sed utf-8

我有一个UTF-8数据文件,其中有一些意外的UTF-8字符序列会破坏数据处理。我需要用空格或任何安全字符替换此序列(数据来自外部源):

options

在bash脚本中,如何使用In Hex: E2 80 8B (​) sed命令等命令行工具替换此字符?我尝试过:

replace

但它不起作用(没有数据被替换)。是否有一种特殊的语法来指定带有“十六进制”字符而不是ascii字符的正则表达式? 使用3字节序列执行“二进制”替换是否可行?

注意:该文件是UTF-8编码的,所以我认为搜索实际序列存在问题,因为它不是utf-8(3字节ASCII)

2 个答案:

答案 0 :(得分:1)

如果字节确实是0xE20x800x8B,则它是utf-8编码的文本。

然后it means

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

用于在某些文本中将单词保持在一起。
并且可以用bash打印:

$ 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

答案 1 :(得分:0)

我有一个用于过滤此类符号的PHP函数。这不是你想要的,但它仍然可以在控制台中运行,只需安装PHP即可。 将singletime<uint64_t>替换为输入文件名,in.txt替换输出文件名并运行脚本(out.txt)。 希望它会有用。

php script_file.php

以下是另外两个用于剥离3&amp; amp;的功能。 4个字节的UTF符号:

<?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;
}
?>