我有一个UTF-8数据文件,其中有一些意外的UTF-8字符序列会破坏数据处理。我需要用空格或任何安全字符替换此序列(数据来自外部源):
options
在bash脚本中,如何使用In Hex: E2 80 8B (​)
或sed
命令等命令行工具替换此字符?我尝试过:
replace
但它不起作用(没有数据被替换)。是否有一种特殊的语法来指定带有“十六进制”字符而不是ascii字符的正则表达式? 使用3字节序列执行“二进制”替换是否可行?
注意:该文件是UTF-8编码的,所以我认为搜索实际序列存在问题,因为它不是utf-8(3字节ASCII)
答案 0 :(得分:1)
如果字节确实是0xE2
,0x80
和0x8B
,则它是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;
}
?>