Board logo

标题: 跨平台printf工具pr [打印本页]

作者: happy886rr    时间: 2017-8-25 21:55     标题: 跨平台printf工具pr

本帖最后由 happy886rr 于 2017-8-26 10:12 编辑
pr  与printf类似,但远超printf。可以对各类文本格式化输出,对各类命令的返回结果进行格式化整理。内嵌表达式计算核心,堪比小型计算器。
(图片为外部链接)


用法
  1. pr -e [格式化表达式] [参数1] [参数2] [参数3] ...
复制代码
由于windows的批处理对%号敏感,我用\代替百分号,因此有了如下的格式化类型字符串
  1. \d 数字
  2. \x 十六进制
  3. \c 字符
  4. \s 字符串
  5. \f 浮点数
  6. \o 八进制
  7. \u 无符号数
  8. \e 科学计数法
  9. \g 科学计数精度
  10. \r 回车
  11. \n 换行
  12. \t tab
  13. \T 显示本地时间字符串
  14. \C 颜色格式化
  15. \, 千分位格式化
复制代码
示例:
显示本地时间
  1. > pr -e\T
  2. Sat, 25 Aug 2017 19:59:12
复制代码
彩色输出
  1. > pr -e"\CW\Cel\Cco\Cm\Ce to \CBat\CHom\Ce" "1|4|8" "1|2|8" "1|8" "2|8" "1|4|8" "1|2" "1|4|8" "1|2|8"
  2. Sat, 25 Aug 2017 19:59:12
复制代码
千分位格式化
  1. > pr -e\, 1234567
  2. 1,234,567
复制代码
用于科学计算输出
  1. > pr -e"Result: \3.6f" sin((pi)/3)
  2. Result: 0.866025
复制代码
用于字符串对齐、文本对齐
  1. > pr -e"\-10.10s" da5da5d12ad21a1d2a1d
  2. > pr -e"\10s" da5
  3. > pr -e"\ 7d"  666
复制代码
用于打印换行特殊字符
  1. > pr -eAafafa\r\nafa+56a\r\nfsaf565ad\r\n
  2. > pr -e\c 7
复制代码
辅助echo实现各类增强功能,用处广,跨平台。更是各类控制台手机终端的必备良器。

源码发行,推荐gcc编译。不提供任何附件下载,请自行编译。
  1. /*
  2.     CONSOLE PRINT TOOL, PR.EXE COPYRIGHT@2017~2019 BY HAPPY
  3.     VERSION 1.0
  4. */
  5. #include   <stdio.h>
  6. #include  <stdlib.h>
  7. #include  <string.h>
  8. #include  <unistd.h>
  9. #include    <math.h>
  10. #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
  11. #include <windows.h>
  12. #endif
  13. #define HELPINFORMATION "\
  14. Console print tool, Copyright@2017~2019, Version 1.0\n\
  15. pr -e[expression] {args...}\n\
  16. \n\
  17. Options:\n\
  18.     -e print expression\n\
  19.     -h help information\n\
  20. \n\
  21. Support math functions:\n\
  22.      pi, e, torad, sin, cos, tan, sinh, cosh, tanh\n\
  23.      arcsin, arccos, arctan, arcsinh, arccosh, arctanh\n\
  24.      sqrt, abs, lg, ln, exp, gamma, rand, round, int, ceil, floor\n"
  25. #define STACK_SIZE 4096
  26. static const char* KEY_WORDS[]= {"e", "pi", "sqrt", "lg", "ln", "sin", "cos", "tan", "arcsin", "arccos", "arctan", "torad", "abs", "round", "floor", "ceil", "exp", "sinh", "cosh", "tanh", "arcsinh", "arccosh", "arctanh", "int", "gamma", "rand", NULL};
  27. char   STACK1[STACK_SIZE]= {0};
  28. char   STACK2[STACK_SIZE]= {0};
  29. double STACK3[STACK_SIZE]= {0};
  30. int prThousandsformatted(char* oStr)
  31. {
  32.     int len = strlen(oStr), rl = len%3, i;
  33.     for(i=0; i<rl; i++)
  34.     {
  35.         putc(oStr[i], stdout);
  36.     }
  37.     if(rl)
  38.         putc(',', stdout);
  39.     for(; i<len; i++)
  40.     {
  41.         putc(oStr[i], stdout);
  42.         if(!((i-rl+1)%3) && i!=len-1)
  43.             putc(',', stdout);
  44.     }
  45.     return 0;
  46. }
  47. long long fact(long long n)
  48. {
  49.     return (n<2) ?1 :n*(fact(n-1));
  50. }
  51. double RevPolishCore(const char* expression)
  52. {
  53.     char   *op=(char*)expression, *S1=STACK1, *S2=STACK2, **key, *cp, *kp;
  54.     double *S3=STACK3, di, ni;
  55.     int    brackets=0;
  56.     STACK3[0]=0;
  57.     while(*op!='\0')
  58.     {
  59.         switch(*op)
  60.         {
  61.         case ' ' :
  62.         case '\t':
  63.         case '\r':
  64.         case '\n':
  65.             op++;
  66.             continue;
  67.         case '(':
  68.             brackets++;
  69.             *(++S1)=*op;
  70.             if(*(op+1)=='-' || *(op+1)=='+')
  71.             {
  72.                 *(S2++)='0', *(S2++)=' ';
  73.             }
  74.             break;
  75.         case ')':
  76.             if(brackets ==0)
  77.             {
  78.                 fputs("The brackets or ')' are not need", stderr);
  79.                 exit(1);
  80.             }
  81.             brackets--;
  82.             while(*S1!='(')
  83.             {
  84.                 *(S2++)=*(S1--);
  85.             }
  86.             S1--;
  87.             break;
  88.         case '+':
  89.         case '-':
  90.             while(S1!=STACK1 && *S1!='(')
  91.             {
  92.                 *(S2++)=*(S1--);
  93.             }
  94.             *(++S1)=*op;
  95.             break;
  96.         case '&':
  97.         case '|':
  98.         case '^':
  99.             while('A'<=(*S1) && (*S1)<='Z')
  100.             {
  101.                 *(S2++)=*(S1--);
  102.             }
  103.             *(++S1)=*op;
  104.             break;
  105.         case '!':
  106.             *(S2++)=*op;
  107.             break;
  108.         case '%':
  109.         case '*':
  110.         case '/':
  111.             while(('A'<=(*S1) && (*S1)<='Z') ||*S1=='%' ||*S1=='*' ||*S1=='/' ||*S1=='^')
  112.             {
  113.                 *(S2++)=*(S1--);
  114.             }
  115.             *(++S1)=*op;
  116.             break;
  117.         default :
  118.             if('a'<=*op && *op<='z')
  119.             {
  120.                 key=(char**)KEY_WORDS;
  121.                 while(*key !=NULL)
  122.                 {
  123.                     cp=op, kp=*key;
  124.                     while((*cp==*kp || *cp+32==*kp) && *kp!='\0')
  125.                     {
  126.                         cp++, kp++;
  127.                     }
  128.                     if(!('a'<=*cp && *cp<='z')  && (*kp=='\0'))
  129.                     {
  130.                         op=cp;
  131.                         break;
  132.                     }
  133.                     key++;
  134.                 }
  135.                 if(*key !=0)
  136.                 {
  137.                     *(S2++)='.';
  138.                     *(S2++)=' ';
  139.                     while('A'<=(*S1) && (*S1)<='Z')
  140.                     {
  141.                         *(S2++)=*(S1--);
  142.                     }
  143.                     *(++S1)=key-(char**)KEY_WORDS+65;
  144.                     continue;
  145.                 }
  146.                 else
  147.                 {
  148.                     fputs("Unrecognized math function\n", stderr);
  149.                     exit(1);
  150.                 }
  151.             }
  152.             else if(('0'<=*op && *op<='9') || (*op=='.'))
  153.             {
  154.                 while(('0'<=*op && *op<='9') || (*op=='.'))
  155.                 {
  156.                     *(S2++)=*(op++);
  157.                 }
  158.                 if('a'<=*op && *op<='z')
  159.                 {
  160.                     fputs("Missing required operator\n", stderr);
  161.                     exit(1);
  162.                 }
  163.                 op--;
  164.                 *(S2++)=' ';
  165.             }
  166.             else
  167.             {
  168.                 fputs("Unrecognized operator\n", stderr);
  169.                 exit(1);
  170.             }
  171.             break;
  172.         }
  173.         op++;
  174.     }
  175.     if(brackets !=0)
  176.     {
  177.         fputs("The brackets '(' are not closed", stderr);
  178.         exit(1);
  179.     }
  180.     while(S1 !=STACK1)
  181.     {
  182.         *(S2++)=*(S1--);
  183.     }
  184.     *S2=' ';
  185.     op=STACK2;
  186.     while(*op!=' ')
  187.     {
  188.         switch(*op)
  189.         {
  190.         case 'A':
  191.             *S3=2.7182818284590452;
  192.             break;
  193.         case 'B':
  194.             *S3=3.1415926535897932;
  195.             break;
  196.         case 'C':
  197.             if(*S3 <0)
  198.             {
  199.                 fputs("Negative numbers have no square root\n", stderr);
  200.                 exit(1);
  201.             }
  202.             *(S3-1)=sqrt(*S3);
  203.             S3--;
  204.             break;
  205.         case 'D':
  206.             if(*S3 <0)
  207.             {
  208.                 fputs("Negative numbers are not logarithmic\n", stderr);
  209.                 exit(1);
  210.             }
  211.             *(S3-1)=log10(*S3);
  212.             S3--;
  213.             break;
  214.         case 'E':
  215.             if(*S3 <0)
  216.             {
  217.                 fputs("Negative numbers have no natural logarithms\n", stderr);
  218.                 exit(1);
  219.             }
  220.             *(S3-1)=log(*S3);
  221.             S3--;
  222.             break;
  223.         case 'F':
  224.             *(S3-1)=sin(*S3);
  225.             S3--;
  226.             break;
  227.         case 'G':
  228.             *(S3-1)=cos(*S3);
  229.             S3--;
  230.             break;
  231.         case 'H':
  232.             if(*S3==3.1415926535897932/2)
  233.             {
  234.                 fputs("The pi/2 has no tangent\n", stderr);
  235.                 exit(1);
  236.             }
  237.             *(S3-1)=tan(*S3);
  238.             S3--;
  239.             break;
  240.         case 'I':
  241.             *(S3-1)=asin(*S3);
  242.             S3--;
  243.             break;
  244.         case 'J':
  245.             *(S3-1)=acos(*S3);
  246.             S3--;
  247.             break;
  248.         case 'K':
  249.             *(S3-1)=atan(*S3);
  250.             S3--;
  251.             break;
  252.         case 'L':
  253.             *(S3-1)=(*S3)*3.1415926535897932/180.0;
  254.             S3--;
  255.             break;
  256.         case 'M':
  257.             *(S3-1)=fabs(*S3);
  258.             S3--;
  259.             break;
  260.         case 'N':
  261.             *(S3-1)=round(*S3);
  262.             S3--;
  263.             break;
  264.         case 'O':
  265.             *(S3-1)=floor(*S3);
  266.             S3--;
  267.             break;
  268.         case 'P':
  269.             *(S3-1)=ceil(*S3);
  270.             S3--;
  271.             break;
  272.         case 'Q':
  273.             *(S3-1)=exp(*S3);
  274.             S3--;
  275.             break;
  276.         case 'R':
  277.             *(S3-1)=sinh(*S3);
  278.             S3--;
  279.             break;
  280.         case 'S':
  281.             *(S3-1)=cosh(*S3);
  282.             S3--;
  283.             break;
  284.         case 'T':
  285.             *(S3-1)=tanh(*S3);
  286.             S3--;
  287.             break;
  288.         case 'U':
  289.             *(S3-1)=asinh(*S3);
  290.             S3--;
  291.             break;
  292.         case 'V':
  293.             *(S3-1)=acosh(*S3);
  294.             S3--;
  295.             break;
  296.         case 'W':
  297.             *(S3-1)=atanh(*S3);
  298.             S3--;
  299.             break;
  300.         case 'X':
  301.             *(S3-1)=(int)(*S3);
  302.             S3--;
  303.             break;
  304.         case 'Y':
  305.             if(*S3 <0)
  306.             {
  307.                 fputs("Negative numbers have no factorial", stderr);
  308.                 exit(1);
  309.             }
  310.             *(S3-1)=tgamma(*S3);
  311.             S3--;
  312.             break;
  313.         case 'Z':
  314.             if(*S3 <0)
  315.             {
  316.                 fputs("A negative number can not be used as a random upper bound", stderr);
  317.                 exit(1);
  318.             }
  319.             else if(*S3 <2)
  320.             {
  321.                 *(S3-1)=rand() % 8192 /8192.0;
  322.             }
  323.             else
  324.             {
  325.                 *(S3-1)=rand() % (int)(*S3);
  326.             }
  327.             S3--;
  328.             break;
  329.         case '+':
  330.             *(S3-1)+=*S3;
  331.             S3--;
  332.             break;
  333.         case '-':
  334.             *(S3-1)-=*S3;
  335.             S3--;
  336.             break;
  337.         case '*':
  338.             *(S3-1)*=*S3;
  339.             S3--;
  340.             break;
  341.         case '%':
  342.         case '/':
  343.             if(*S3 !=0)
  344.             {
  345.                 if(*op=='%')
  346.                 {
  347.                     *(S3-1)=(int)*(S3-1) % (int)*S3;
  348.                 }
  349.                 else
  350.                 {
  351.                     *(S3-1)/=*S3;
  352.                 }
  353.             }
  354.             else
  355.             {
  356.                 fputs("Divisor is zero error\n", stderr);
  357.                 exit(1);
  358.             }
  359.             S3--;
  360.             break;
  361.         case '|':
  362.             *(S3-1) =(int)(*(S3-1)) | (int)(*S3);
  363.             S3--;
  364.             break;
  365.         case '&':
  366.          *(S3-1) =(int)(*(S3-1)) & (int)(*S3);
  367.             S3--;
  368.             break;
  369.         case '^':
  370.             if(*(S3-1)==0 && *S3<0)
  371.             {
  372.                 fputs("Function pow's divisor is zero error\n", stderr);
  373.                 exit(1);
  374.             }
  375.             *(S3-1)=pow(*(S3-1), *S3);
  376.             S3--;
  377.             break;
  378.         case '!':
  379.             if(*S3 <0)
  380.             {
  381.                 fputs("Negative numbers have no factorial\n", stderr);
  382.                 exit(1);
  383.             }
  384.             *S3=fact((long long)(*S3));
  385.             break;
  386.         default :
  387.             di=0, ni=1;
  388.             while('0'<=*op && *op<='9')
  389.             {
  390.                 di=10*di+(*op)-'0';
  391.                 op++;
  392.             }
  393.             if(*op=='.')
  394.             {
  395.                 op++;
  396.                 while('0'<=*op && *op<='9')
  397.                 {
  398.                     di=10*di+(*op)-'0';
  399.                     op++, ni*=10;
  400.                 }
  401.             }
  402.             *(++S3)=di/ni;
  403.             break;
  404.         }
  405.         op++;
  406.     }
  407.     if (isinf(*S3)||isnan(*S3))
  408.     {
  409.         fputs("Overflow or illegal operation is calculated", stderr);
  410.         exit(1);
  411.     }
  412.     return *S3;
  413. }
  414. //MAIN主函数入口
  415. int main(int argc, char** argv)
  416. {
  417.     if ((argc==1) || (argc==2 && !strcasecmp(argv[1], "-h")))
  418.     {
  419.         fprintf(stderr, HELPINFORMATION);
  420.         return 0;
  421.     }
  422.     int i = 2;
  423.     char* prExp = NULL;
  424.     if ((argc > 1) && (argv[1][0]=='-' && (argv[1][1]=='e' || argv[1][1]=='E')))
  425.     {
  426.         prExp = (argv[1][2] != '\0') ?(argv[1]+2) :((argc > 2)?(argv[i++]):NULL);
  427.     }
  428.     if (prExp == NULL)
  429.     {
  430.         fprintf(stderr, HELPINFORMATION);
  431.         return 1;
  432.     }
  433.     srand((int)getpid());
  434.     char prBuf[STACK_SIZE], *t=prBuf, *p=prExp;
  435.     static char nowTime[128];
  436.     static const char* timeFormatGMT = "%a, %d %b %Y %H:%M:%S";
  437. #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
  438. HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);
  439. WORD orgCOLOR;
  440. CONSOLE_SCREEN_BUFFER_INFO buffINFO;
  441. GetConsoleScreenBufferInfo(handle_out, &buffINFO);
  442. orgCOLOR=buffINFO.wAttributes;
  443. #endif
  444.     while(*p)
  445.     {
  446.         if (*p == '\\')
  447.         {
  448.             t=prBuf;
  449.             *t++ = '%';
  450.             p++;
  451.             while(*p=='+' || *p=='-' || *p=='0' || *p==' ' || *p=='#' || ('0'<=*p && *p<='9') || *p=='.')
  452.                 *t++ = *p++;
  453.             switch (*p)
  454.             {
  455.             case 'n':
  456.                 printf("\n");
  457.                 break;
  458.             case 'r':
  459.                 printf("\r");
  460.                 break;
  461.             case 't':
  462.                 printf("\t");
  463.                 break;
  464.             case 'T':
  465.              {
  466.                 time_t timeNow = time((time_t*)0);
  467.                 strftime(nowTime, sizeof(nowTime), timeFormatGMT, (const struct tm*)localtime(&timeNow));
  468.                 printf("%s", nowTime);
  469.              }
  470.              break;
  471.             
  472. #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
  473.             case 'C':
  474.                 if(i >= argc)
  475.                     break;
  476.                 SetConsoleTextAttribute(handle_out, (int)RevPolishCore(argv[i++]));
  477.              break;
  478. #endif
  479.             case '\\':
  480.                 printf("\\");
  481.                 break;
  482.             case ',':
  483.                 if(i >= argc)
  484.                     break;
  485.                 prThousandsformatted(argv[i++]);
  486.                 break;
  487.             case 's':
  488.                 *t++ = *p;
  489.                 *t='\0';
  490.                 if(i >= argc)
  491.                     break;
  492.                 printf(prBuf, (char*)argv[i++]);
  493.                 break;
  494.             case 'c':
  495.                 *t++ = 'c';
  496.                 *t='\0';
  497.                 if(i >= argc)
  498.                     break;
  499.                 printf(prBuf, (char)(int)RevPolishCore(argv[i++]));
  500.                 break;
  501.             case 'd':
  502.                 *t++ = 'd';
  503.                 *t='\0';
  504.                 if(i >= argc)
  505.                     break;
  506.                 printf(prBuf, (int)RevPolishCore(argv[i++]));
  507.                 break;
  508.             case 'o':
  509.                 *t++ = 'o';
  510.                 *t='\0';
  511.                 if(i >= argc)
  512.                     break;
  513.                 printf(prBuf, (int)RevPolishCore(argv[i++]));
  514.                 break;
  515.             case 'e':
  516.             case 'E':
  517.                 *t++ = *p;
  518.                 *t='\0';
  519.                 if(i >= argc)
  520.                     break;
  521.                 printf(prBuf, RevPolishCore(argv[i++]));
  522.                 break;
  523.             case 'g':
  524.             case 'G':
  525.                 *t++ = *p;
  526.                 *t='\0';
  527.                 if(i >= argc)
  528.                     break;
  529.                 printf(prBuf, RevPolishCore(argv[i++]));
  530.                 break;
  531.             case 'x':
  532.             case 'X':
  533.                 *t++ = *p;
  534.                 *t='\0';
  535.                 if(i >= argc)
  536.                     break;
  537.                 printf(prBuf, (int)RevPolishCore(argv[i++]));
  538.                 break;
  539.             case 'u':
  540.                 *t++ = 'u';
  541.                 *t='\0';
  542.                 if(i >= argc)
  543.                     break;
  544.                 printf(prBuf, (unsigned int)RevPolishCore(argv[i++]));
  545.                 break;
  546.             case 'f':
  547.                 *t++ = 'f';
  548.                 *t='\0';
  549.                 if(i >= argc)
  550.                     break;
  551.                 printf(prBuf, RevPolishCore(argv[i++]));
  552.                 break;
  553.             default:
  554.                 fprintf(stderr, "Unknow flag '%c'", *p);
  555.                 return 1;
  556.             }
  557.             p++;
  558.         }
  559.         t=prBuf;
  560.         while(*p && *p != '\\')
  561.             *t++ = *p++;
  562.         *t='\0';
  563.         printf("%s", prBuf);
  564.         if(i >= argc && argc!=2)
  565.             break;
  566.     }
  567.    
  568. #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)   
  569. SetConsoleTextAttribute(handle_out, orgCOLOR);
  570. #endif
  571.     return 0;
  572. }
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2