删除 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'
得到一个ç,如果没有,你需要上面的函数。
我想删除一个 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'
得到一个ç,如果没有,你需要上面的函数。