我编写了一个shell函数,该函数使用awk
将UTF-8
编码的字符串转换为JSON字符串。
json_stringify() {
LANG=C awk '
BEGIN {
for ( i = 1; i < ARGC; i++ )
print json_stringify(ARGV[i])
}
function json_stringify( str, _str, _out ) {
if( ! ("\" in _ESC_) )
for ( i = 1; i <= 127; i++ )
_ESC_[ sprintf( "%c", i) ] = sprintf( "\u%04x", i )
_str = str
_out = """
while ( match( _str, /["\[:cntrl:]]/ ) ) {
_out = _out substr(_str,1,RSTART-1) _ESC_[substr(_str,RSTART,RLENGTH)]
_str = substr( _str, RSTART + RLENGTH )
}
return _out _str """
}
' "$@"
}
感觉我错过了一些琐碎的事情,因为当我运行(在bash中(时:
json_stringify 'A"B' 'CD' $'b f t r n'
我得到:
"Au0022B"
而我的预期输出是:
"Au0022B"
"Cu005cD"
"u0008 u000c u0009 u000d u000a"
我的代码中可能有什么问题?
我看到的一个问题是i
在BEGIN/for
循环和function/for
循环中同时用作循环变量,并且由于i
在函数中没有声明为"local",因此整个脚本只使用了一个i
实例。净结果是函数将i
推出到远远超过ARGC
的127
,因此BEGIN
块仅循环一次(i=1
(,因为在第二循环i=127
上。
两种可能的修复方法:
将i
声明为函数的本地,例如:
function json_stringify( str, _str, _out, i ) {
或者在其中一个循环中使用不同的循环变量(例如j
(,例如
# in the BEGIN block:
for ( j = 1; j < ARGC; j++ )
print json_stringify(ARGV[j])
# or in the function:
for ( j = 1; j <= 127; j++ )
_ESC_[ sprintf( "%c", j) ] = sprintf( "\u%04x", j )
测试每个可能的修复程序可以让我生成:
"Au0022B"
"Cu005cD"
"u0008 u000c u0009 u000d u000a"
控制变量范围-关于此主题的简短讨论。
@Fravadona:这里有一种简单的方法可以轻松地映射所有字节,而不会产生任何错误/警告消息/抑制
-
表
ordU8[]
返回的链的第一个整数是预先计算的偏移量,以简化UTF-8
代码点从其组成字节的反计算: -
b
、t
、n
、v
、f
、r
、