以下是我编写的bash文件,用于将C文件中的所有C++样式(//)注释转换为C样式(/**/).
#!/bin/bash
lang=`echo $LANG`
# It's necessary to change the local setting. I don't know why.
export LANG=C
# Can comment the following statement if there is not dos2unix command.
dos2unix -q $1
sed -i -e 's;^\([[:blank:]]*\)//\(.*\);\1/* \2 */;' $1
export LANG=$lang
Run Code Online (Sandbox Code Playgroud)
有用.但我发现了一个我无法解释的问题.默认情况下,我的本地设置为en_US.UTF-8.在我的C代码中,有用中文写的评论,比如
// some english ??????
Run Code Online (Sandbox Code Playgroud)
如果我不更改本地设置,即不运行语句export LANG = C,我会得到
/* some english */??????
Run Code Online (Sandbox Code Playgroud)
代替
/* some english ??????*/
Run Code Online (Sandbox Code Playgroud)
我不知道为什么.我只是通过尝试和错误找到解决方案.
在阅读Jonathan Leffler的回答后,我认为我犯了一些错误导致了一些误解.在这个问题中,这些中文单词是在谷歌浏览器中输入的,而不是我的C文件中的实际单词.一些中文注释只是意味着一些中文评论.
现在我在Windows XP中的Visual C++ 6.0中输入了一些英文一些中文注释,并将c文件复制到Debian.然后我就运行sed -i -e's; ^([[:blank:]])//(.);\1 /\2 /;' 1美元,得到了
/* some english ?? */????
Run Code Online (Sandbox Code Playgroud)
我认为不同的字符编码(GB18030,GBK,UTF-8?)会导致不同的结果.
以下是我在Debian上获得的结果
~/sandbox$ uname -a
Linux xyt-dev 2.6.30-1-686 #1 SMP Sat Aug 15 19:11:58 UTC 2009 i686 GNU/Linux
~/sandbox$ echo $LANG
en_US.UTF-8
~/sandbox$ cat tt.c | od -c -t x1
0000000 / / s o m e e n g l i s h
2f 2f 20 73 6f 6d 65 20 65 6e 67 6c 69 73 68 20
0000020 322 273 320 251 326 320 316 304 327 242 312 315
d2 bb d0 a9 d6 d0 ce c4 d7 a2 ca cd
0000034
~/sandbox$ ./convert_comment_style_cpp2c.sh tt.c
~/sandbox$ cat tt.c | od -c -t x1
0000000 / * s o m e e n g l i s h
2f 2a 20 20 73 6f 6d 65 20 65 6e 67 6c 69 73 68
0000020 322 273 320 251 * / 326 320 316 304 327 242 312 315
20 d2 bb d0 a9 20 2a 2f d6 d0 ce c4 d7 a2 ca cd
0000040
~/sandbox$
Run Code Online (Sandbox Code Playgroud)
我认为这些汉字编码有2个字节(Unicode).
还有另一个例子:
~/sandbox$ cat tt.c | od -c -t x1
0000000 / / I n W i n d o w : 250 250 ?
2f 2f 20 49 6e 57 69 6e 64 6f 77 3a 20 a8 a8 3f
0000020 1 ?
31 3f
0000022
~/sandbox$ ./convert_comment_style_cpp2c.sh tt.c
~/sandbox$ cat tt.c | od -c -t x1
0000000 / * I n W i n d o w : *
2f 2a 20 20 49 6e 57 69 6e 64 6f 77 3a 20 20 2a
0000020 / 250 250 ? 1 ?
2f a8 a8 3f 31 3f
Run Code Online (Sandbox Code Playgroud)
你在做哪个平台?您的sed脚本在MacOS X上运行正常而不更改区域设置.Linux终端对中文字符不太满意,但没有设置使用UTF-8.此外,它所包含的字符串的十六进制转储包含中文启动的零字节0x00,这可能导致混淆.(我注意到你的正则表达式在注释文本开头之前会添加一个空格// with a space.)
'odx'命令用法是一个十六进制转储程序.
$ echo "// some english ??????" > x3.utf8
$ odx x3.utf8
0x0000: 2F 2F 20 73 6F 6D 65 20 65 6E 67 6C 69 73 68 20 // some english
0x0010: E4 B8 80 E4 BA 9B E4 B8 AD E6 96 87 E6 B3 A8 E9 ................
0x0020: 87 8A 0A ...
0x0023:
$ utf8-unicode x3.utf8
0x2F = U+002F
0x2F = U+002F
0x20 = U+0020
0x73 = U+0073
0x6F = U+006F
0x6D = U+006D
0x65 = U+0065
0x20 = U+0020
0x65 = U+0065
0x6E = U+006E
0x67 = U+0067
0x6C = U+006C
0x69 = U+0069
0x73 = U+0073
0x68 = U+0068
0x20 = U+0020
0xE4 0xB8 0x80 = U+4E00
0xE4 0xBA 0x9B = U+4E9B
0xE4 0xB8 0xAD = U+4E2D
0xE6 0x96 0x87 = U+6587
0xE6 0xB3 0xA8 = U+6CE8
0xE9 0x87 0x8A = U+91CA
0x0A = U+000A
$ sed 's;^\([[:blank:]]*\)//\(.*\);\1/* \2 */;' x3.utf8
/* some english ?????? */
$
Run Code Online (Sandbox Code Playgroud)
所有这些看起来干净整洁.
我将x3.utf8文件复制到Linux机器箱,并将其转储.然后我在上面运行了sed脚本,一切似乎都没问题:
$ odx x3.utf8
0x0000: 2F 2F 20 73 6F 6D 65 20 65 6E 67 6C 69 73 68 20 // some english
0x0010: E4 B8 80 E4 BA 9B E4 B8 AD E6 96 87 E6 B3 A8 E9 ................
0x0020: 87 8A 0A ...
0x0023:
$ sed 's;^\([[:blank:]]*\)//\(.*\);\1/* \2 */;' x3.utf8 | odx
0x0000: 2F 2A 20 20 73 6F 6D 65 20 65 6E 67 6C 69 73 68 /* some english
0x0010: 20 E4 B8 80 E4 BA 9B E4 B8 AD E6 96 87 E6 B3 A8 ...............
0x0020: E9 87 8A 20 2A 2F 0A ... */.
0x0027:
$
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.我也尝试过:
$ echo $LANG
en_US.UTF-8
$ echo $LC_CTYPE
$ env | grep LC_
$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
$ cat x3.utf8
// some english ??????
$ echo $(<x3.utf8)
// some english ??????
$ sed 's;^\([[:blank:]]*\)//\(.*\);\1/* \2 */;' x3.utf8
/* some english ?????? */
$
Run Code Online (Sandbox Code Playgroud)
所以,终端名义上毕竟是在UTF-8工作,它肯定显示数据正常.
但是,如果我在终端回显字符串,它就会陷入困境.当我把字符串切换到Linux终端时,它说:
$ echo "// some english d8d^G:
> "
// some english d8d:
$
Run Code Online (Sandbox Code Playgroud)
和蜂鸟.
$ echo "// some english d8d^G:
> " | odx
0x0000: 2F 2F 20 73 6F 6D 65 20 65 6E 67 6C 69 73 68 20 // some english
0x0010: 64 38 64 07 3A 0A 0A d8d.:..
0x0017:
$
Run Code Online (Sandbox Code Playgroud)
我不太清楚该怎么做.我认为这意味着输入端的bash某些东西存在一些问题,但我不太确定.我的结果也略有不一致.我第一次尝试时,得到了:
$ cat > xxx
's;^\([[:blank:]]*\)//\(.*\);\1/* \2 */;'
// some english d8^@d:^[d8-f^Gf3(i^G
$ odx xxx
0x0000: 27 73 3B 5E 5C 28 5B 5B 3A 62 6C 61 6E 6B 3A 5D 's;^\([[:blank:]
0x0010: 5D 2A 5C 29 2F 2F 5C 28 2E 2A 5C 29 3B 5C 31 2F ]*\)//\(.*\);\1/
0x0020: 2A 20 5C 32 20 2A 2F 3B 27 0A 2F 2F 20 73 6F 6D * \2 */;'.// som
0x0030: 65 20 65 6E 67 6C 69 73 68 20 64 38 00 64 3A 1B e english d8.d:.
0x0040: 64 38 2D 66 07 66 33 28 69 07 0A 0A d8-f.f3(i...
0x004C:
$
Run Code Online (Sandbox Code Playgroud)
在该十六进制转储中,您可以看到0x00字节(偏移量0x003C).这出现在你得到结束评论的位置,并且可能会混淆null sed; 但整个输入是如此混乱,很难知道该怎么做.