删除 ascii 字符并替换为非 ascii 字符

remove ascii character and replace with non-ascii

我想删除一个 ASCII 字符,然后用非 ASCII 字符替换它。我的代码是:

sed -e 's/[\d100\d130]/g' 

解释一下:我想用“135”(ASCII,十进制)替换“100”(ASCII,十进制)。简而言之,我想替换 2 个字母,其中一个将被删除。此代码有效?

这不是有效的 sed 命令:

sed -e 's/[\d100\d135]/g'

也许像

sed -e 's/[\d100]/[\d135]/g'

在快速测试中,这个 "works":

echo 'd' | sed -e 's/[\d100]/[\d135]/g'

建议的 tr 命令很接近,但 135 转换为八进制 207,例如,

tr '4' '7'

在 UTF-8 系统中,您可能 运行 遇到 135 的问题,因为它本身不是有效的单字节代码。 135 对应的 UTF-8 编码使用两个字节,例如 27

echo 'd' | sed -e 's/\d100/\d194\d135/g'

可能是 OP 的意图。使用我的语言环境 en_US.UTF-8,它会生成一个 UTF-8 编码的 135(在 vi-like-emacs 中显示为 \u0087:这恰好是有效的 UTF-8,但不是可打印字符,因为它实际上是 Unicode 中的控制字符)。提供有关 OP 打算用于输出的更多信息,可以提供更好的建议。

十进制的 100 是 "d",而 135 是扩展的 ascii "ç" 或 cedilla。
将 a 设置为所有值:

a="$(printf "$(printf '\x%x' {95..105} 135 135 135 {130..140} )")"

这两项工作:

echo "$a"| tr '4' '7'
echo "$a"| sed -e $'s/4/7/g'    # Note the $

如果你想看这个字符,写一个文件,用IBM850编码打开。在具有该功能的文本编辑器中,您将看到(三倍于 cedilla ç,并且 d 也发生了变化):

_`abcçefghiçççéâäàåçêëèïî

UTF-8

对于 utf-8,情况有所不同。
UTF-8 中的 cedilla 是十进制的 231(十六进制 E7),它是这样输出的:

$ printf $'\U0E7'
ç

要获取 127 (7F) 到 255 (FF) 以上值的 UTF-8 可能会很棘手,因为 Bash 会误解某些值。此函数将允许从值转换为正确的字符:

function chr_utf8 {
    local val
    [[ ${2?Missing Ordinal Value} -lt 0x80000000 ]] || return 1

    if [[  -lt 0x100 &&  -ge 0x80 ]]; then

        # bash 4.2 incorrectly encodes
        # \U000000ff as \xff so encode manually
        printf -v val "\%03o\%03o" $(( (>>6)|0xc0 )) $(( (&0x3f)|0x80 ))
    else
        printf -v val '\U%08x' ""
    fi
    printf -v ${1?Missing Dest Variable} ${val}
}

chr_utf8 a 231
echo "$a"

结论

解决方法其实很简单:

echo "aadddcc" | sed $'s/d/\U0E7/g'       # echo $'\U0E7' should output ç
aaçççcc

测试你从echo $'\U0E7'得到一个ç,如果没有,你需要上面的函数。