将ASCII字符转换为"<Uxxx>"unicode表示法的脚本

Mes*_*ion 2 python string bash ascii

我正在对Linux语言环境文件/usr/share/i18n/locales(如pt_BR)进行一些更改,并且%d-%m-%Y %H:%M必须在Unicode中指定格式字符串(如),其中每个(在本例中为ASCII)字符表示为<U00xx>.

所以像这样的文字:

LC_TIME
d_t_fmt "%a %d %b %Y %T %Z"
d_fmt   "%d-%m-%Y"
t_fmt   "%T"
Run Code Online (Sandbox Code Playgroud)

一定是:

LC_TIME
d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
d_fmt   "<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0059>"
t_fmt   "<U0025><U0054>"
Run Code Online (Sandbox Code Playgroud)

因此,我需要一个命令行脚本(无论是bash,Python,Perl还是其他东西),它会接受输入%d-%m-%Y并将其转换为<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0059>.

在输入字符串中的所有字符将ASCII字符(从0x200x7F),所以这实际上是一个票友"字符到十六进制的字符串"的转换.

有人可以帮帮我吗?我在bash脚本编写方面的技能非常有限,在Python中更糟糕.

优雅,解释的解决方案的奖金.

谢谢!

(顺便说一句,这将是我之前的问题的"反向"脚本)

Sie*_*geX 7

每个带文件输入的字符

如果你想将文件的每个字符转换为unicode表示,那么这将是一个简单的单行

while IFS= read -r -n1 c;do printf "<U%04X>" "'$c"; done < ./infile
Run Code Online (Sandbox Code Playgroud)

STDIN上的每个字符

如果你想制作一个类似于unix的工具,将STDIN上的输入转换为类似unicode的输出,那么使用:

uni(){ c=$(cat); for((i=0;i<${#c};i++)); do printf "<U%04X>" "'${c:i:1}"; done; }
Run Code Online (Sandbox Code Playgroud)

概念证明

$ echo "abc" | uni
<U0061><U0062><U0063>
Run Code Online (Sandbox Code Playgroud)

只有双引号之间的字符

#!/bin/bash

flag=0
while IFS= read -r -n1 c; do
    if [[ "$c" == '"' ]]; then
        ((flag^=1))
        printf "%c" "$c"
    elif [[ "$c" == $'\0' ]]; then
        echo
    elif ((flag)); then
        printf "<U%04X>" "'$c"
    else
        printf "%c" "$c"
    fi
done < /path/to/infile
Run Code Online (Sandbox Code Playgroud)

概念证明

$ cat ./unime
LC_TIME
d_t_fmt "%a %d %b %Y %T %Z"
d_fmt   "%d-%m-%Y"
t_fmt   "%T"
abday "Dom";"Seg";/
here is a string with "multiline
quotes";/

$ ./uni.sh
LC_TIME
d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
d_fmt   "<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0059>"
t_fmt   "<U0025><U0054>"
abday "<U0044><U006F><U006D>";"<U0053><U0065><U0067>";/
here is a string with "<U006D><U0075><U006C><U0074><U0069><U006C><U0069><U006E><U0065>
<U0071><U0075><U006F><U0074><U0065><U0073>";/
Run Code Online (Sandbox Code Playgroud)

说明

非常简单

  1. while IFS= read -r -n1 c;:一次迭代输入的一个字符(via -n1)并将char存储在变量中c.在IFS=-r标志有这么的read内建不会尝试做分词或解释转义序列,分别.
  2. if [[ "$c" == '"' ]];:如果当前char是双引号
  3. ((flag^=1)):从0-> 1或1-> 0反转标志的值
  4. elif [[ "$c" == $'\0' ]];:如果当前char是NUL,那么echo换行
  5. elif ((flag)):如果flag为1,则执行unicode音译
  6. printf "<U%04X>" "'$c":执行unicode音译的魔力.请注意,之前的单引号$c是强制性的,因为它告诉printf我们给它一个数字的ASCII表示.
  7. else printf "%c" "$c":打印出没有执行unicode音译的角色


ken*_*ytm 5

使用Python

#!/usr/bin/env python3.2
import sys
text = sys.argv[1]
encoded = "".join("<U{0:04X}>".format(ord(char)) for char in text)
print(encoded)
Run Code Online (Sandbox Code Playgroud)

用法:

$ python3 file.py "enter_input"
<U0065><U006E><U0074><U0065><U0072><U005F><U0069><U006E><U0070><U0075><U0074>
Run Code Online (Sandbox Code Playgroud)

(相同的脚本应该适用于python 3.x和2.x.只需将shebang中的版本更改为您拥有的版本.)

说明:

  1. 我们需要导入sys模块读取命令行参数.

  2. sys.argv列表是所有命令行参数的列表.条目[0]是程序名,条目[1]是第一个参数,等等.

  3. f(char) for char in text是一个生成器表达式.它将循环text变量中的每个字符,然后对其应用函数f,最后将结果作为惰性列表(可迭代)收集.

  4. ord(char) 找到角色的Unicode代码点.

  5. "<U{0:04X}>".format(x)是一个字符串格式化方法,如名称所述.格式字符串需要1个输入x,并格式化为04X格式,表示前导零,宽度4,大写十六进制.

  6. "".join(it)连接惰性列表中的所有元素(可迭代)it.这""意味着分隔符是一个空字符串.

  7. print(encoded)将字符串写入encodedstdout.