AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 495643
Accepted
Paulo Ney
Paulo Ney
Asked: 2019-01-21 11:30:58 +0800 CST2019-01-21 11:30:58 +0800 CST 2019-01-21 11:30:58 +0800 CST

文件中的奇怪字符

  • 772

我有一个 UTF-8 文件,其中包含一个奇怪的字符——对我来说就像

<96>

这就是它的显示方式vi

vi 截图

以及它是如何出现的gedit

gedit 截图

以及它在 LibreOffice 下的显示方式

LibreOffice 截图

这使得一系列基本的 Unix 工具行为不端,包括:

  1. cat file使角色消失,more以及
  2. 我无法在 vi/vim 中复制和粘贴——它甚至找不到自己
  3. grep也无法显示任何内容,就好像该角色不存在一样。

该程序file运行良好,并将其识别为 UTF-8 文件。我也知道,由于文件的性质,它很可能来自网络上的复制和粘贴,并且该字符最初代表 EMDASH。

我的基本问题是:

  1. 这个文件有什么问题吗?
  2. 如何在同一文件中搜索它的其他出现?
  3. 如何查找可能包含相同问题/字符的其他文件?

该文件可以在这里找到:file.txt

character-encoding unicode
  • 3 3 个回答
  • 9288 Views

3 个回答

  • Voted
  1. Best Answer
    Michael Homer
    2019-01-21T12:05:19+08:002019-01-21T12:05:19+08:00

    该文件包含 bytes C2 96,它们是代码点 U+0096 的UTF-8编码。该代码点是C1 控制字符之一,通常称为 SPA“保护区域开始”(或“保护区域”)。这对于任何现代系统都不是一个有用的字符,但它的存在不太可能有害。

    其原始来源可能是某个单字节 8 位编码中的字节 0x96,该字节在途中某处被错误地转码。可能这最初是一个Windows CP1252破折号“-”,在该编码中具有字节值 96 - 大多数其他可能的候选者在位置 80-9F 上都有控制集 - 已被翻译为 UTF-8,就好像它是拉丁语一样 - 1 ( ISO/IEC 8859-1 ),这并不罕见。如您所见,这将导致字节被解释为控制字符并相应地进行翻译。


    您可以使用该工具修复此文件,该iconv工具是 glibc 的一部分。

    iconv -f utf-8 -t iso-8859-1 < mwe.txt | iconv -f cp1252 -t utf-8
    

    为我生成您的最小示例的正确版本。其工作原理是首先将 UTF-8 转换为 latin-1(反转之前的误译),然后将其重新解释为cp1252 以正确地将其转换回 UTF-8。

    但是,它确实取决于真实文件中的其他内容。如果您在其他地方有 Latin-1 之外的字符,它将失败,因为它无法在第一步正确编码这些字符。

    如果你没有 iconv,或者它对真实文件不起作用,你可以直接使用 sed 替换字节:

    LC_ALL=C sed -e $'s/\xc2\x96/\xe2\x80\x93/g' < mwe.txt
    

    这将替换C2 96为 UTF-8 破折号编码E2 80 93。您也可以通过将其更改\xe2\x80\x93为--.


    你可以用类似的方式 grep。我们LC_ALL=C用来确保我们正在读取实际字节,而不是grep解释:

    LC_ALL=C grep -R $'\xc2\x96` .
    

    将在此目录下的所有位置列出这些字节出现。如果您有混合内容,您可能希望将其限制为仅文本文件,因为二进制文件将相当频繁地包含任何字节对。

    • 27
  2. user38573
    2019-01-21T12:04:31+08:002019-01-21T12:04:31+08:00

    0x96 是 Windows 代码页 1252 中的短划线。c2它前面的字节似乎是双角字符中的默认第一个字节。其他人可以更准确地解释它。

    要搜索其他匹配项,请在命令模式下将光标放在它上面,点击yl(拉出一个字符),然后键入/<Ctrl>+r"。(ctrl+r 允许您将寄存器的内容插入到命令中,并且该"寄存器是最后被拉出的任何内容)。

    如果您希望它在终端中呈现,只需将其替换为两个连字符即可。如果那是您拥有的 bibtex 文件,那么两个连字符是键入它的适当方式。

    为了展示如何找到该字符的出现,您可以通过 hexdump 工具(如xxd.

    $ cat tmp | xxd | grep c296
    00000000: 7061 6765 733d 7b31 c296 3935 7d2c 0a70  pages={1..95},.p
    00000020: 6765 733d 7b31 c296 3935 7d2c 0a70 6167  ges={1..95},.pag
    00000040: 733d 7b31 c296 3935 7d2c 0a70 6167 6573  s={1..95},.pages
    00000060: 7b31 c296 3935 7d2c 0a70 6167 6573 3d7b  {1..95},.pages={
    00000080: c296 3935 7d2c 0a70 6167 6573 3d7b 31c2  ..95},.pages={1.
    00000090: 9639 357d 2c0a 7061 6765 733d 7b31 c296  .95},.pages={1..
    000000b0: 357d 2c0a 7061 6765 733d 7b31 c296 3935  5},.pages={1..95
    000000d0: 2c0a 7061 6765 733d 7b31 c296 3935 7d2c  ,.pages={1..95},
    000000f0: 7061 6765 733d 7b31 c296 3935 7d2c 0a70  pages={1..95},.p
    00000110: 6765 733d 7b31 c296 3935 7d2c 0a70 6167  ges={1..95},.pag
    00000130: 733d 7b31 c296 3935 7d2c 0a70 6167 6573  s={1..95},.pages
    00000150: 7b31 c296 3935 7d2c 0a70 6167 6573 3d7b  {1..95},.pages={
    
    • 2
  3. user232326
    2019-01-26T23:49:12+08:002019-01-26T23:49:12+08:00

    文件中的文本是pages = {1113},,是的,它看起来像数字1113,但实际上在第一个之后有一个不同的字符1。而且,是的,您可以从该网页的编辑链接复制粘贴字符串以获取编码字符。

    我们可以使用一些工具查看字符串内部:

    $ a='pages = {1113},'
    

    或者,为了明确并允许在不使用编辑页面的情况下轻松复制粘贴:

    $ a=$(printf 'pages = {1\xc2\x96113},') 
    
    $ echo "$a" | od -An -tx1c
      70  61  67  65  73  20  3d  20  7b  31  c2  96  31  31  33  7d
       p   a   g   e   s       =       {   1 302 226   1   1   3   }
      2c  0a
       ,  \n
    
    $ echo "$a" | sed -n l
    pages = {1\302\226113},$
    
    $ echo "$a" | xxd
    00000000: 7061 6765 7320 3d20 7b31 c296 3131 337d  pages = {1..113}
    00000010: 2c0a
    

    因此,字符是两个字节值c2 96(十六进制)或302 226(八进制)。
    它可能是字节值的 UTF-8 编码96,或者表示为 Unicode 字符:U-0096.

    该值在目前的 UTF-8 或更好的 ISO-8859-1 中是控制字符(维基百科页面)和(Unicode PDF)的 C1 区域中的控制字符,十进制从 128 到 159。具体来说,U-0096 被称为“START OF GUARDED AREA”或SPA。

    该值(dec 150)超出了 ASCII 范围(0-127)并且(在过去)用于表示几个字符,具体取决于所使用的代码页。假设它以前是一个破折号(标记范围 1-113),在 Windows-1252(Microsoft 页面)(维基百科 1252)中编码并称为破折号(这是两个破折号en和em)(维基百科的破折号)或简单地说,用外行的话来说,破折号(-)。


    Q1:这个文件有什么问题吗?

    并非如此,控制字符是有效字符,很少使用但仍然有效。

    但是您可以用破折号替换它们以使编辑更容易。

    <file.txt sed 's/\xc2\x96/-/'
    

    Q2 - 我如何在同一个文件中搜索它的其他出现?

    sed -n '/\xc2\x96/p'             # will print lines that contain that character.
    

    或者,grep 可以搜索字符(颜色突出显示将不可见,因为字符不可打印)并打印该行。

    c="$(printf "\U96")" ; grep "$c" file.txt
    

    或更广泛地说,查找该控制字符范围内的所有字符并列出包含此类字符的文件:

    grep -rlP "[\x80-\x9f]"    
    

    Q3 - 我如何 grep 查找可能包含相同问题/字符的其他文件?

    这将列出 ( -l) 匹配该字符的文件。

    grep -rlP "\x96"
    
    • 1

相关问题

  • 如何翻译 Unicode 字符?[复制]

  • 变音符号的问题(无法输入终端+无法打开文件)

  • 如何让`less`理解代码页?

  • 无法使用键盘键入分音符

  • 将波浪号和横杠堆叠在字母上

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve