使用 sed eval 标志在 shell 管道中将“/U+[0-9A-Fa-f]{4}/”替换为正确的 unicode 字符

使用 sed eval 标志在 shell 管道中将“/U+[0-9A-Fa-f]{4}/”替换为正确的 unicode 字符

我正在尝试正确地可视化文件中列出的现有字符/usr/include/X11/keysymdef.h

它有这样的行:

#define XK_onethird    0x0ab0  /* U+2153 VULGAR FRACTION ONE THIRD */
#define XK_twothirds   0x0ab1  /* U+2154 VULGAR FRACTION TWO THIRDS */
#define XK_onefifth    0x0ab2  /* U+2155 VULGAR FRACTION ONE FIFTH */

我想像这样显示它们:

#define XK_onethird    0x0ab0  /* ⅓ VULGAR FRACTION ONE THIRD */
#define XK_twothirds   0x0ab1  /* ⅔ VULGAR FRACTION TWO THIRDS */
#define XK_onefifth    0x0ab2  /* ⅕ VULGAR FRACTION ONE FIFTH */

我试过:

$ sed -e 's/U+\([0-9A-Fa-f]\{4\}\)/\u\1/' < /usr/include/X11/keysymdef.h

这只是“忽略”了\u。所以,把它归结为一些sed带有 Pilcrow“¶” 的测试用例:

$ echo 00B6 | sed -re $'s/(....)/echo "\u00B6"/e'
¶       # Good, display works, lets get the capture group:
$ echo 00B6 | sed -re $'s/(....)/echo "\u00B6 \\1"/e'
¶ 00B6  # So far, so good, lets prefix \u again:
$ echo 00B6 | sed -re $'s/(....)/echo "\u00B6 \u\\1"/e'
¶ 00B6  # Huh? Ok, trying double-wrapping
$ echo 00B6 | sed -re $'s/(....)/echo "\u00B6 \\u\\1"/e'
¶ 00B6  # Hey, where did the '\\u' go? Ok, try something else:
$ echo 00B6 | sed -re $'s/(....)/echo $(echo "\u00B6 \u\\1")/e'
¶ 00B6  # I give up

(注意:我刚刚也尝试了上述的一些变体printf。没有变化)

我缺少什么?为什么我不能使用评估标志sed像那样?

编辑:我知道,这可以用其他语言/工具来解决while read echo eval和解决,并且赞赏(+1d)答案。

然而,对于这个问题,我最感兴趣的是一个解决方案sed或者知道为什么上述命令会产生此输出和/或为什么这是不可能的。

答案1

使用 Perl:

perl -CS -pe 's/\bU\+([\dA-Fa-f]{4})\b/chr(hex($1))/eg' /usr/include/X11/keysymdef.h

这告诉 perl 查找U+0000,将 转换0000为十六进制,然后用该数字表示的字符替换它。

如果你想替换文件的内容,你可以这样做:

perl -i -CD -pe 's/\bU\+([\dA-Fa-f]{4})\b/chr(hex($1))/eg' /path/to/file

答案2

将(修改后的)sed 输出按行传递echo -e ""

sed -e 's/U+\([0-9A-Fa-f]\{4\}\)/\\u\1/' </usr/include/X11/keysymdef.h |
while read -r line;do echo -e "$line";done 

相关内容