免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 10470 | 回复: 26
打印 上一主题 下一主题

[文本处理] BASH版本的base64 [复制链接]

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-12-31 22:59 |只看该作者 |倒序浏览
本帖最后由 damcool 于 2014-01-03 09:22 编辑

AWK版本的base64编解码脚本有很多限制,特别是在busybox下,作为新年礼物写了一些BASH版本的。如果busybox有hexdump的话。基本上没什么问题了。速度还可以吧。
更新说明
1、去除xargs对脚本兼容性影响
2、加入对管道输入的支持
  1. #!/bin/bash

  2. ################################################################################
  3. # Function Name:   HELP_USAGE                                                   
  4. # Description:     Function to display the usage of the script                  
  5. # Parameters:      None                                                         
  6. # Return:          Help messages                                                
  7. # Called By:       Script Main Loop->Script Parameters' Handler                 
  8. # History:         2013-Dec-31 Initial Edition                       RobinHoo  
  9. ################################################################################

  10. function help_usage(){
  11. cat <<EOF
  12. BASE64 ENCODE & DECODE BASH SCRIPT
  13. Usage: $PROGNAME [OPTION]... [FILE]
  14.   -d, --decode Decode the base64 encoded file
  15.   -h, --help   Show current help message of the script usages
  16.    

  17. Please Report Script Bugs to $AUTHOR_MAIL
  18. EOF
  19. exit 1
  20. }

  21. function BASE64ENCODE()
  22. {
  23.         hexdump -ve '1/1 "%d "' < "$FNAME"|awk -v B64="$BASE64CODE" '{for(i=1;i<=NF;i+=3){t=0;t=$i*256*256+$(i+1)*256+$(i+2);for(j=3;j>=0;j--){c=(i+2-j<=NF)?substr(B64,int(t/2^(6*j))+1,1):"=";printf("%c",c);t%=2^(6*j);if (++k==76) printf"\n";k%=76}}}'
  24. }

  25. function BASE64DECODE()
  26. {
  27.         local buff=""
  28.         for buff in $(cat < "$FNAME"|awk -v B64="$BASE64CODE" '{while(length()){split(substr($0,1,4),a,"");$0=substr($0,5);t=0;for(i=3;i>=0;i--) t=t+2^(6*i)*((a[4-i]=="=")?0:index(B64,a[4-i])-1);for (i=2;i>=0;i--) if (a[4-i]!="="){printf("\\x%x",t/2^(8*i));t=t%2^(8*i)}}printf"\n"}');do printf "$buff"; done
  29. }
  30. BASE_DIR=$(cd "$(dirname "$0")" && pwd)
  31. PROGNAME=$(basename "$0")
  32. AUTHOR_MAIL="robin.hoo@hotmail.com"
  33. BASE64CODE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  34. DECODE=0;
  35. HELP=0;
  36. FNAME="";
  37. while [ $# -gt 0 ]
  38. do
  39.     case "$1" in
  40.     (-d)        DECODE=1;;
  41.     (-h)        HELP=1;;
  42.     (--decode)  DECODE=1;;
  43.     (--help)    HELP=1;;
  44.     (-*)        echo "$PROGNAME: error - unrecognized option or parameter $1" 1>&2; HELP=1;break;;
  45.     (*)         [ "$FNAME" != "" ] && echo "$PROGNAME: error - more than one file name " 1>&2 && HELP=1 && break || FNAME="$1";;
  46.     esac
  47.     shift
  48. done
  49. [ $# -gt 1 ] && HELP=1
  50. [ "$FNAME" == "" ] && FNAME="/dev/stdin"
  51. [ $HELP -eq 1 ] && help_usage

  52. [ $DECODE -eq 1 ] && BASE64DECODE || BASE64ENCODE
复制代码

论坛徽章:
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
2 [报告]
发表于 2014-01-01 02:12 |只看该作者
本帖最后由 bikkuri 于 2014-01-01 03:01 编辑

膜拜了!之前我用awk写的base64编码和解码程序确实效率很低,在CPU 200MHz的Busybox上编码或者解码一个大约4000字节的二进制文件需要大约一分钟时间。
说实话,对您的脚本中的awk的部分我看得还不是很懂,需要时间消化。
对您的脚本我有三个问题:
1、貌似function help_usage(){ 这样定义函数的方式是awk,在shell下应该去掉function;
2、编码的部分我在busybox下测试了没有问题,但是解码的部分在busybox下测试报错而且解码文件比原文件还要大:
  1. root@unknown:/tmp/test# ./base64.sh -d a.64 > b.gz
  2. xargs: illegal option -- i
  3. root@unknown:/tmp/test# ls -l
  4. -rw-r--r--    1 root     root            36 Jan  1 02:01 a.64
  5. -rw-r--r--    1 root     root            26 Jan  1 02:01 a.gz
  6. -rw-r--r--    1 root     root            48 Jan  1 02:31 b.gz
  7. -rwxr-xr-x    1 root     root          2183 Jan  1 02:29 base64.sh
  8. root@unknown:/tmp/test# more b.gz
  9. SDRzSUFPZDJ3MUlDQS9OSXpjbko1d0lBRmpXV01RWUFBQUE9root@unknown:/tmp/test#
复制代码
3、解码时在busybox下awk无法输出NULL字符,不知道您是怎么解决的?

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
3 [报告]
发表于 2014-01-01 10:22 |只看该作者
1.Please forget the AWK solution at all
2.Check out the xargs usage in busybox & adjust the decode line accordingly.

Happy New Year !

论坛徽章:
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
4 [报告]
发表于 2014-01-01 10:46 |只看该作者
I found the xargs information in busybox as below:
  1. xargs
  2. xargs [OPTIONS] [PROG [ARGS]]
  3. Run PROG on every item given by standard input
  4. Options:
  5. -p Ask user whether to run each command
  6. -r Do not run command if input is empty
  7. -0 Input is separated by NUL characters
  8. -t Print the command on stderr before execution
  9. -e[STR] STR stops input processing
  10. -n N Pass no more than N args to PROG
  11. -s N Pass command line of no more than N bytes
  12. -x Exit if size is exceeded
复制代码
which option should I use to replace the -i option?

damcool 发表于 2014-01-01 10:22
1.Please forget the AWK solution at all
2.Check out the xargs usage in busybox & adjust the decode  ...

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
5 [报告]
发表于 2014-01-01 11:00 |只看该作者
Replace line 32
  1. cat "$FNAME"|awk -v B64="$BASE64CODE" '{while(length()){split(substr($0,1,4),a,"");$0=substr($0,5);t=0;for(i=3;i>=0;i--) t=t+2^(6*i)*((a[4-i]=="=")?0:index(B64,a[4-i])-1);for (i=2;i>=0;i--) if (a[4-i]!="="){printf("\\\\\\x%X",t/2^(8*i));t=t%2^(8*i)}}printf"\n"}'|xargs -i printf {}
复制代码
with below line
  1. for raw_data in $(cat "$FNAME"|awk -v B64="$BASE64CODE" '{while(length()){split(substr($0,1,4),a,"");$0=substr($0,5);t=0;for(i=3;i>=0;i--) t=t+2^(6*i)*((a[4-i]=="=")?0:index(B64,a[4-i])-1);for (i=2;i>=0;i--) if (a[4-i]!="="){printf("\\\\\\x%X",t/2^(8*i));t=t%2^(8*i)}}printf"\n"}'); do printf "$raw_data";done
复制代码

论坛徽章:
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
6 [报告]
发表于 2014-01-01 11:13 |只看该作者
After I replaced the line with the new one.
The decode output is double as it should be.
  1. root@unknown:/tmp/test# echo "Hello" > a
  2. root@unknown:/tmp/test# gzip a
  3. root@unknown:/tmp/test# ./base64_encode_decode.sh a.gz > a.64
  4. root@unknown:/tmp/test# ./base64_encode_decode.sh -d a.64 > b.gz
  5. root@unknown:/tmp/test# ls -l
  6. -rw-r--r--    1 root     root            36 Jan  1 11:12 a.64
  7. -rw-r--r--    1 root     root            26 Jan  1 11:12 a.gz
  8. -rw-r--r--    1 root     root            52 Jan  1 11:12 b.gz
  9. -rwxr-xr-x    1 root     root          2197 Jan  1 11:10 base64_encode_decode.sh
  10. root@unknown:/tmp/test#
复制代码
damcool 发表于 2014-01-01 11:00
Replace line 32with below line

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
7 [报告]
发表于 2014-01-01 11:32 |只看该作者
That's what I could do now, if you can't manage to make it right I can't neither.

论坛徽章:
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
8 [报告]
发表于 2014-01-01 12:04 |只看该作者
I tested the script on Linux also.
With the xargs line, the decode output is correct, but with the replaced line, the decode output is incorrect.
So the problem is with the replaced line...

damcool 发表于 2014-01-01 11:32
That's what I could do now, if you can't manage to make it right I can't neither.

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
9 [报告]
发表于 2014-01-01 14:13 |只看该作者
本帖最后由 damcool 于 2014-01-01 14:15 编辑

嗨~!现在的年轻人一点点代码调试能力都没有!刚刚找到电脑,看了一下原来的代码只要去掉xargs后面的-i和{}就可以正常运行了。
  1. cat "$FNAME"|awk -v B64="$BASE64CODE" '{while(length()){split(substr($0,1,4),a,"");$0=substr($0,5);t=0;for(i=3;i>=0;i--) t=t+2^(6*i)*((a[4-i]=="=")?0:index(B64,a[4-i])-1);for (i=2;i>=0;i--) if (a[4-i]!="="){printf("\\\\\\x%X",t/2^(8*i));t=t%2^(8*i)}}printf"\n"}'|xargs printf
复制代码
或者
  1. for raw_data in $(cat "$FNAME"|awk -v B64="$BASE64CODE" '{while(length()){split(substr($0,1,4),a,"");$0=substr($0,5);t=0;for(i=3;i>=0;i--) t=t+2^(6*i)*((a[4-i]=="=")?0:index(B64,a[4-i])-1);for (i=2;i>=0;i--) if (a[4-i]!="="){printf("\\\\x%X",t/2^(8*i));t=t%2^(8*i)}}printf"\n"}'); do printf "$raw_data";done
复制代码

论坛徽章:
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
10 [报告]
发表于 2014-01-01 15:40 |只看该作者
刚才测试了一下,确实可以正常输出了!
谢谢您的指点!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP