免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: bikkuri
打印 上一主题 下一主题

[文本处理] 用awk写的base64编码脚本,大家帮忙修改一下! [复制链接]

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
11 [报告]
发表于 2013-12-25 17:33 |只看该作者
处理纯文本好像没什么问题:
  1. root@unknown:/tmp/test# echo Hello |./base64encode.sh
  2. Source: Hello
  3. byte1=72 byte2=101 byte3=108
  4. base1=18 base2=6 base3=21 base4=44
  5. Result=SGVs
  6. Source: lo
  7. byte1=108 byte2=111 byte3=0
  8. base1=27 base2=6 base3=60 base4=0
  9. Result=SGVsbG8=
  10. SGVsbG8=root@unknown:/tmp/test#
复制代码

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
12 [报告]
发表于 2013-12-25 18:27 |只看该作者
我知道了,要处理二进制字节的话,asc函数里char的取值范围应该是0-255。
这是一个比较明显的错误。等下我回去修改一下试试。
还有一个问题就是为什么输出的字节数会多几倍。
从上面的debug结果看,最后输出result的时候输出了三次同样的内容。

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
13 [报告]
发表于 2013-12-25 23:04 |只看该作者
本帖最后由 bikkuri 于 2013-12-25 23:15 编辑

把asc函数里char的取值范围改成0-255之后,
  1. function asc(char,l_found)
  2. {
  3.         for (i=0;i<=255;i++){
  4.         if (sprintf("%c",i)==char) l_found=i;
  5.         }
  6.         return l_found;
  7. }
复制代码
大于127的高位字节可以进行处理了,但是当程序碰到0的时候还是出现了问题。
  1. Source: ^_‹^H Length: 3
  2. byte1=31 byte2=139 byte3=8
  3. base1=7 base2=56 base3=44 base4=8
  4. Result=H4sI
  5. H4sISource: &thorn;^M&raquo;R^B^CóH&Iacute;&Eacute;&Eacute;&ccedil;^B Length: 13
  6. byte1=254 byte2=13 byte3=187
  7. base1=63 base2=32 base3=54 base4=59
  8. Result=H4sI/g27
  9. Source: R^B^CóH&Iacute;&Eacute;&Eacute;&ccedil;^B Length: 10
  10. byte1=82 byte2=2 byte3=3
  11. base1=20 base2=32 base3=8 base4=3
  12. Result=H4sI/g27UgID
  13. Source: óH&Iacute;&Eacute;&Eacute;&ccedil;^B Length: 7
  14. byte1=243 byte2=72 byte3=205
  15. base1=60 base2=52 base3=35 base4=13
  16. Result=H4sI/g27UgID80jN
  17. Source: &Eacute;&Eacute;&ccedil;^B Length: 4
  18. byte1=201 byte2=201 byte3=231
  19. base1=50 base2=28 base3=39 base4=39
  20. Result=H4sI/g27UgID80jNycnn
  21. Source: ^B Length: 1
  22. byte1=2 byte2=0 byte3=0
  23. base1=0 base2=32 base3=0 base4=0
  24. Result=H4sI/g27UgID80jNycnnAg==
  25. H4sI/g27UgID80jNycnnAg==Source: ^V5–1^F Length: 5
  26. byte1=22 byte2=53 byte3=150
  27. base1=5 base2=35 base3=22 base4=22
  28. Result=H4sI/g27UgID80jNycnnAg==FjWW
  29. Source: 1^F Length: 2
  30. byte1=49 byte2=6 byte3=0
  31. base1=12 base2=16 base3=24 base4=0
  32. Result=H4sI/g27UgID80jNycnnAg==FjWWMQY=
  33. H4sI/g27UgID80jNycnnAg==FjWWMQY=H4sI/g27UgID80jNycnnAg==FjWWMQY=H4sI/g27UgID80jNycnnAg==FjWWMQY=
复制代码
把应该处理的字节和实际被处理的字节做一个对比,可以发现程序在对0的处理出现异常:
  1. [Origin] -> [Should be]   |  [Result]
  2. 1F 8B 08 -> 31 139 8      |  31 139 8
  3. 00 FE 0D -> 0 254 13      |  254 13 187
  4. BB 52 02 -> 187 82 2      |  82 2 3
  5. 03 F3 48 -> 3 243 72      |  243 72 205
  6. CD C9 C9 -> 205 201 201   |  201 201 231
  7. E7 02 00 -> 231 2 0       |  2 0 0
  8. 16 35 96 -> 22 53 150     |  22 53 150
  9. 31 06 00 -> 49 6 0        |  49 6 0
  10. 00 00    -> 0 0           |

  11. [26 bytes]                   [24 bytes]
复制代码
怀疑是asc函数中的if (sprintf("%c",i)==char) l_found=i;这一句中sprintf函数,在Busybox下无法正常输出sprintf("%c", 0),因此asc函数返回值为空。

我试了在asc函数中对l_found先赋0值,这样即使sprintf函数在碰到0,无法输出sprintf("%c",0),这个函数还是可以返回最初赋的0值。
  1. function asc(char,l_found)
  2. {
  3.         l_found=0;
  4.         for (i=0;i<=255;i++){
  5.         if (sprintf("%c",i)==char) l_found=i;
  6.         }
  7.         return l_found;
  8. }
复制代码
但是修改后再次执行,结果没有任何变化。不知道是什么原因。

另外最后的result值显示3遍的原因也还是不清楚。

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
14 [报告]
发表于 2013-12-25 23:39 |只看该作者
本帖最后由 bikkuri 于 2013-12-26 01:32 编辑

看来不是asc函数的问题。
看程序对$0长度的处理可以发现Busybox下的awk在碰到0的时候就认为字符串结束了!
也就是说0被转义了!
源字符串1F 8B 08 00 FE 0D BB 52 02 03 F3 48 CD C9 C9 E7 02 00 16 35 96 31 06 00 00 00被awk当成了3个字符串
  1. 1F 8B 08 - Length: 3
  2. FE 0D BB 52 02 03 F3 48 CD C9 C9 E7 02 - Length: 13
  3. 16 35 96 31 06 - Length: 5
复制代码
有什么办法让awk不把0当作字符串结束呢?或者说如何让awk不转义字符串中间的0呢?有没有办法取消awk的分隔符设定呢?

程序最后输出result的时候输出了3遍同样的内容,也很有可能是因为awk把result当成是3个字符串的编码结果,在分别输出3个字符串的编码结果时却把相同的result输出了3遍。
所以现在的关键问题是要让awk知道这不是3个字符串,而是一个字符串。
各位awk高手有什么好的意见吗?

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
15 [报告]
发表于 2013-12-26 00:32 |只看该作者
本帖最后由 bikkuri 于 2013-12-26 00:38 编辑

看来确实是分隔符的问题。
  1. root@unknown:/tmp/test# echo -e "Hello \n World!"|./base64encode.sh
  2. Source: Hello  Length: 6
  3. byte1=72 byte2=101 byte3=108
  4. base1=18 base2=6 base3=21 base4=44
  5. Result=SGVs
  6. Source: lo  Length: 3
  7. byte1=108 byte2=111 byte3=32
  8. base1=27 base2=6 base3=60 base4=32
  9. Result=SGVsbG8g
  10. SGVsbG8gSource:  World! Length: 7
  11. byte1=32 byte2=87 byte3=111
  12. base1=8 base2=5 base3=29 base4=47
  13. Result=SGVsbG8gIFdv
  14. Source: rld! Length: 4
  15. byte1=114 byte2=108 byte3=100
  16. base1=28 base2=38 base3=49 base4=36
  17. Result=SGVsbG8gIFdvcmxk
  18. Source: ! Length: 1
  19. byte1=33 byte2=0 byte3=0
  20. base1=8 base2=16 base3=0 base4=0
  21. Result=SGVsbG8gIFdvcmxkIQ==
  22. SGVsbG8gIFdvcmxkIQ==root@unknown:/tmp/test#
复制代码
哪位awk高手教我如何取消awk的分隔符啊!拜谢了!
  1. root@unknown:/tmp/test# echo -e "Hello \0 World!"|./base64encode.sh
  2. Source: Hello  Length: 6
  3. byte1=72 byte2=101 byte3=108
  4. base1=18 base2=6 base3=21 base4=44
  5. Result=SGVs
  6. Source: lo  Length: 3
  7. byte1=108 byte2=111 byte3=32
  8. base1=27 base2=6 base3=60 base4=32
  9. Result=SGVsbG8g
  10. SGVsbG8gSource:  World! Length: 7
  11. byte1=32 byte2=87 byte3=111
  12. base1=8 base2=5 base3=29 base4=47
  13. Result=SGVsbG8gIFdv
  14. Source: rld! Length: 4
  15. byte1=114 byte2=108 byte3=100
  16. base1=28 base2=38 base3=49 base4=36
  17. Result=SGVsbG8gIFdvcmxk
  18. Source: ! Length: 1
  19. byte1=33 byte2=0 byte3=0
  20. base1=8 base2=16 base3=0 base4=0
  21. Result=SGVsbG8gIFdvcmxkIQ==
  22. SGVsbG8gIFdvcmxkIQ==root@unknown:/tmp/test#
复制代码

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
16 [报告]
发表于 2013-12-26 10:26 |只看该作者
本帖最后由 jason680 于 2013-12-26 10:33 编辑

回复 15# bikkuri

change the RS and FS in awk or you need the new version of awk or rebuild your busybox
$ echo -e "Hello \0 World"  | awk 'BEGIN{RS="\x00"}{print $0}'
Hello
World

$ echo -e "Hello \0 World"  | awk 'BEGIN{RS="\x55\xaa\x66\xbb"}{print $0}'
Hello  World


-------------------------------
I didn't have your system with busybox, I try it in Solaris that also have old version of awk

in Solaris, some issue in awk
$ echo -e "Hello \0 World"  | /usr/xpg4/bin/awk '{print $0}' | od -t x1
0000000 48 65 6c 6c 6f 20 0a
0000007

$ echo -e "Hello \0 World"  |  od -t x1
0000000 48 65 6c 6c 6f 20 00 20 57 6f 72 6c 64 0a
0000016
   
in Linux, without issue
$ echo -e "Hello \0 World"  | awk '{print $0}' | od -t x1
0000000 48 65 6c 6c 6f 20 00 20 57 6f 72 6c 64 0a
0000016

论坛徽章:
771
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
17 [报告]
发表于 2013-12-26 10:44 |只看该作者
回复 15# bikkuri
好像确实有这个问题
CentOS6.4
  1. echo -e "Hello\0World"|awk '1'

  2. HelloWorld
复制代码
Solaris 5.10
  1. echo -e "Hello\0World"|/usr/xpg4/bin/awk '1'

  2. Hello
复制代码
gawk和nawk的区别?

论坛徽章:
771
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
18 [报告]
发表于 2013-12-26 12:00 |只看该作者
回复 14# bikkuri

找了一上午,没找到怎么忽略输入中的\0的。
楼主看一一下下面这段,gawk外的其他awk
都是以\0为结束的。


Advanced Notes: RS = "\0" Is Not Portable

There are times when you might want to treat an entire data file as a single record. The only way to make this happen is to give RS a value that you know doesn't occur in the input file. This is hard to do in a general way, such that a program always works for arbitrary input files.

You might think that for text files, the NUL character, which consists of a character with all bits equal to zero, is a good value to use for RS in this case:

       

BEGIN { RS = "\0" }  # whole file becomes one record?

gawk in fact accepts this, and uses the NUL character for the record separator. However, this usage is not portable to other awk implementations.

All other awk implementations(15) store strings internally as C-style strings. C strings use the NUL character as the string terminator. In effect, this means that `RS = "\0"' is the same as `RS = ""'. (d.c.)


The best way to treat a whole file as a single record is to simply read the file in, one record at a time, concatenating each record onto the end of the previous ones.

   

论坛徽章:
0
19 [报告]
发表于 2013-12-26 13:28 |只看该作者
在经历过无数次惨痛的关键字冲突导致莫名错误之后,有一点心得。
在命名变量时,为其添加适当的前缀。

譬如一个变量,表示时间,很自然想到
time=xxx
但是time是Shell下的命令,不宜用作变量。那么可以
varTime=xxx
这里用variable(变量)的缩写var作为前缀,并且使用了驼峰命名法。整个变量清晰易懂,可读性较高,同时避免任何可能的关键字冲突。
函数我一般使用function的缩写func作为前缀。

仅个人拙见,供楼主参考。

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
20 [报告]
发表于 2013-12-26 18:55 |只看该作者
刚才在busybox上试了一下楼上几位的命令,好像无论怎么改FS和RS,awk都会在"\0"的地方把字符串分隔成两个字符串。
  1. root@unknown:/tmp/test# echo -e "Hello \0 World"  |hexdump -C
  2. 00000000  48 65 6c 6c 6f 20 00 20  57 6f 72 6c 64 0a        |Hello . World.|
  3. 0000000e
  4. root@unknown:/tmp/test# echo -e "Hello \0 World"  |awk '{print $0}'|hexdump -C
  5. 00000000  48 65 6c 6c 6f 20 0a 20  57 6f 72 6c 64 0a        |Hello . World.|
  6. 0000000e
  7. root@unknown:/tmp/test# echo -e "Hello \0 World"  |awk 'BEGIN{FS="\0"}{print $0}'|hexdump -C
  8. 00000000  48 65 6c 6c 6f 20 0a 20  57 6f 72 6c 64 0a        |Hello . World.|
  9. 0000000e
  10. root@unknown:/tmp/test# echo -e "Hello \0 World"  |awk 'BEGIN{FS="\0x55\0x66"}{print $0}'|hexdump -C
  11. 00000000  48 65 6c 6c 6f 20 0a 20  57 6f 72 6c 64 0a        |Hello . World.|
  12. 0000000e
  13. root@unknown:/tmp/test# echo -e "Hello \0 World"  |awk '1'|hexdump -C
  14. 00000000  48 65 6c 6c 6f 20 0a 20  57 6f 72 6c 64 0a        |Hello . World.|
  15. 0000000e
  16. root@unknown:/tmp/test# echo -e "Hello \0 World"  |awk 'BEGIN{RS="\0"}{print $0}'|hexdump -C
  17. 00000000  48 65 6c 6c 6f 20 0a                              |Hello .|
  18. 00000007
  19. root@unknown:/tmp/test# echo -e "Hello \0 World"  |awk 'BEGIN{RS="\0x55\0x66"}{print $0}'|hexdump -C
  20. 00000000  48 65 6c 6c 6f 20 0a                              |Hello .|
  21. 00000007
  22. root@unknown:/tmp/test#
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP