【问题标题】:Bash: how to get the complete substring of a match in a string?Bash:如何获取字符串中匹配项的完整子字符串?
【发布时间】:2017-10-18 13:38:35
【问题描述】:

我有一个 TXT 文件,它是从一台 Windows 机器上运来的,并以 ISO-8859-1 编码。我的 Qt 应用程序应该读取此文件,但 QString 仅支持 UTF-8(我想避免使用 QByteArray)。我一直在努力寻找在 Qt 中做到这一点的方法,所以我决定编写一个小脚本来为我进行转换。我完全按照我的情况编写它没有问题,但我想让它更通用 - 适用于所有 ISO-8859 编码。

到目前为止,我有以下内容:

#!/usr/bin/env bash

output=$(file -i $1)

# If the output contains any sort of ISO-8859 substring
if echo "$output" | grep -qi "ISO-8859"; then
  # Retrieve actual encoding
  encoding=...
  # run iconv to convert
  iconv -f $encoding $1 -t UTF-8 -o $1
else
  echo "Text file not encoded in ISO-8859"
fi

我正在苦苦挣扎的部分是如何获取已在grep 命令中成功处理的完整子字符串。

假设我有文件helloworld.txt,它以 ISO-8859-15 编码。在这种情况下

$~: ./fixEncodingToUtf8 helloworld.txt
stations.txt: text/plain; charset=iso-8859-15

将是终端中的output。在grep 内部找到iso-8859(因为我使用-i 标志,它以不区分大小写的方式处理输入)。此时脚本需要“提取”整个子字符串,即不仅仅是iso-8859,而是iso-8859-15,并将其存储在encoding变量中,以便稍后与iconv一起使用(不区分大小写(呸!)它涉及编码的名称)。

注意:上面的脚本可以进一步扩展,只需检索charset 后面的值并将其用于encoding。然而,这有一个巨大的缺陷——如果输入文件的编码具有比 UTF-8 更大的字符集(简单示例:UTF-16 和 UTF-32)怎么办?

【问题讨论】:

    标签: bash encoding utf-8 grep iso-8859-1


    【解决方案1】:

    或者使用下面的 bash 功能

    $ str="stations.txt: text/plain; charset=iso-8859-15"
    $ echo "${str#*=}"
    iso-8859-15
    

    保存在变量中

    $ myvar="${str#*=}"
    

    【讨论】:

    • 酷。在@JNevill 的回答下查看我的评论。
    【解决方案2】:

    您可以使用cutawk 来获取:

    awk:

    encoding=$(echo $output | awk -F"=" '{print $2}')
    

    剪切:

    encoding=$(echo $output | cut -d"=" -f2)
    

    我认为您可以直接将其提供给您的 iconv 命令并将您的脚本简化为:

    iconv -f $(file $1 | cut -d"=" -f2) -t UTF-8 file
    

    【讨论】:

    • 太棒了。所以基本上你在= 处拆分output 的内容并得到后半部分。剩下的唯一问题是:file -i $1 的输出是否保证以...=ENCODING 结束,或者是否可以在编码后添加其他内容?
    • 没有。我认为从file 命令中看到的内容并不能保证这一切。不过请查看man file,可能有一种方法可以强制命令的输出仅转储字符集。不过,您可能会遇到一些奇怪的边缘情况。
    • 我看过很多例子,最后都有编码(对于这个特定的调用)。但是,将不胜感激更通用的解决方案。我在man 页面中找不到与此相关的任何内容。
    • 这有点奇怪。使用 UTF-16LE 编码文档上的 file -i 标志,我得到 test3.txt: application/octet-stream 所以......这有点折腾。我想您可以捕获 encoding 变量并测试它是否已设置。如果不是,则可能将其作为边缘情况单独处理。我不确定是否有万能的解决方案。
    【解决方案3】:

    好吧,在这种情况下,这是毫无意义的……

    $ file --brief --mime-encoding "$1"
    iso-8859-15
    

    文件手册

    -b, --brief
            Do not prepend filenames to output lines (brief mode).
    ...
    --mime-type, --mime-encoding
            Like -i, but print only the specified element(s).
    

    【讨论】:

    • :O 我在阅读文档时错过了这个论点... faceplam
    猜你喜欢
    • 1970-01-01
    • 2017-05-26
    • 2020-08-23
    • 2020-04-05
    • 1970-01-01
    • 2022-11-30
    • 2015-10-14
    • 2021-11-22
    • 1970-01-01
    相关资源
    最近更新 更多