本帖最后由 happy886rr 于 2017-8-26 10:12 编辑
pr 与printf类似,但远超printf。可以对各类文本格式化输出,对各类命令的返回结果进行格式化整理。内嵌表达式计算核心,堪比小型计算器。
(图片为外部链接)
用法- pr -e [格式化表达式] [参数1] [参数2] [参数3] ...
复制代码 由于windows的批处理对%号敏感,我用\代替百分号,因此有了如下的格式化类型字符串- \d 数字
- \x 十六进制
- \c 字符
- \s 字符串
- \f 浮点数
- \o 八进制
- \u 无符号数
- \e 科学计数法
- \g 科学计数精度
- \r 回车
- \n 换行
- \t tab
- \T 显示本地时间字符串
- \C 颜色格式化
- \, 千分位格式化
复制代码 示例:
显示本地时间- > pr -e\T
- Sat, 25 Aug 2017 19:59:12
复制代码 彩色输出
- > 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"
- Sat, 25 Aug 2017 19:59:12
复制代码 千分位格式化- > pr -e\, 1234567
- 1,234,567
复制代码 用于科学计算输出- > pr -e"Result: \3.6f" sin((pi)/3)
- Result: 0.866025
复制代码 用于字符串对齐、文本对齐- > pr -e"\-10.10s" da5da5d12ad21a1d2a1d
- > pr -e"\10s" da5
- > pr -e"\ 7d" 666
复制代码 用于打印换行特殊字符- > pr -eAafafa\r\nafa+56a\r\nfsaf565ad\r\n
- > pr -e\c 7
复制代码 辅助echo实现各类增强功能,用处广,跨平台。更是各类控制台手机终端的必备良器。
源码发行,推荐gcc编译。不提供任何附件下载,请自行编译。- /*
- CONSOLE PRINT TOOL, PR.EXE COPYRIGHT@2017~2019 BY HAPPY
- VERSION 1.0
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <math.h>
-
- #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
- #include <windows.h>
- #endif
-
- #define HELPINFORMATION "\
- Console print tool, Copyright@2017~2019, Version 1.0\n\
- pr -e[expression] {args...}\n\
- \n\
- Options:\n\
- -e print expression\n\
- -h help information\n\
- \n\
- Support math functions:\n\
- pi, e, torad, sin, cos, tan, sinh, cosh, tanh\n\
- arcsin, arccos, arctan, arcsinh, arccosh, arctanh\n\
- sqrt, abs, lg, ln, exp, gamma, rand, round, int, ceil, floor\n"
-
- #define STACK_SIZE 4096
- 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};
- char STACK1[STACK_SIZE]= {0};
- char STACK2[STACK_SIZE]= {0};
- double STACK3[STACK_SIZE]= {0};
-
- int prThousandsformatted(char* oStr)
- {
- int len = strlen(oStr), rl = len%3, i;
- for(i=0; i<rl; i++)
- {
- putc(oStr[i], stdout);
- }
- if(rl)
- putc(',', stdout);
- for(; i<len; i++)
- {
- putc(oStr[i], stdout);
- if(!((i-rl+1)%3) && i!=len-1)
- putc(',', stdout);
- }
- return 0;
- }
-
- long long fact(long long n)
- {
- return (n<2) ?1 :n*(fact(n-1));
- }
-
- double RevPolishCore(const char* expression)
- {
- char *op=(char*)expression, *S1=STACK1, *S2=STACK2, **key, *cp, *kp;
- double *S3=STACK3, di, ni;
- int brackets=0;
- STACK3[0]=0;
-
- while(*op!='\0')
- {
- switch(*op)
- {
- case ' ' :
- case '\t':
- case '\r':
- case '\n':
- op++;
- continue;
-
- case '(':
- brackets++;
- *(++S1)=*op;
- if(*(op+1)=='-' || *(op+1)=='+')
- {
- *(S2++)='0', *(S2++)=' ';
- }
- break;
-
- case ')':
- if(brackets ==0)
- {
- fputs("The brackets or ')' are not need", stderr);
- exit(1);
- }
- brackets--;
- while(*S1!='(')
- {
- *(S2++)=*(S1--);
- }
- S1--;
- break;
-
- case '+':
- case '-':
- while(S1!=STACK1 && *S1!='(')
- {
- *(S2++)=*(S1--);
- }
- *(++S1)=*op;
- break;
-
- case '&':
- case '|':
- case '^':
- while('A'<=(*S1) && (*S1)<='Z')
- {
- *(S2++)=*(S1--);
- }
- *(++S1)=*op;
- break;
-
- case '!':
- *(S2++)=*op;
- break;
-
- case '%':
- case '*':
- case '/':
- while(('A'<=(*S1) && (*S1)<='Z') ||*S1=='%' ||*S1=='*' ||*S1=='/' ||*S1=='^')
- {
- *(S2++)=*(S1--);
- }
- *(++S1)=*op;
- break;
-
- default :
- if('a'<=*op && *op<='z')
- {
- key=(char**)KEY_WORDS;
- while(*key !=NULL)
- {
- cp=op, kp=*key;
- while((*cp==*kp || *cp+32==*kp) && *kp!='\0')
- {
- cp++, kp++;
- }
- if(!('a'<=*cp && *cp<='z') && (*kp=='\0'))
- {
- op=cp;
- break;
- }
- key++;
- }
- if(*key !=0)
- {
- *(S2++)='.';
- *(S2++)=' ';
- while('A'<=(*S1) && (*S1)<='Z')
- {
- *(S2++)=*(S1--);
- }
- *(++S1)=key-(char**)KEY_WORDS+65;
- continue;
- }
- else
- {
- fputs("Unrecognized math function\n", stderr);
- exit(1);
- }
-
- }
- else if(('0'<=*op && *op<='9') || (*op=='.'))
- {
- while(('0'<=*op && *op<='9') || (*op=='.'))
- {
- *(S2++)=*(op++);
- }
- if('a'<=*op && *op<='z')
- {
- fputs("Missing required operator\n", stderr);
- exit(1);
- }
- op--;
- *(S2++)=' ';
-
- }
- else
- {
- fputs("Unrecognized operator\n", stderr);
- exit(1);
- }
- break;
- }
- op++;
- }
-
- if(brackets !=0)
- {
- fputs("The brackets '(' are not closed", stderr);
- exit(1);
- }
-
- while(S1 !=STACK1)
- {
- *(S2++)=*(S1--);
- }
- *S2=' ';
-
- op=STACK2;
- while(*op!=' ')
- {
- switch(*op)
- {
- case 'A':
- *S3=2.7182818284590452;
- break;
- case 'B':
- *S3=3.1415926535897932;
- break;
- case 'C':
- if(*S3 <0)
- {
- fputs("Negative numbers have no square root\n", stderr);
- exit(1);
- }
- *(S3-1)=sqrt(*S3);
- S3--;
- break;
- case 'D':
- if(*S3 <0)
- {
- fputs("Negative numbers are not logarithmic\n", stderr);
- exit(1);
- }
- *(S3-1)=log10(*S3);
- S3--;
- break;
- case 'E':
- if(*S3 <0)
- {
- fputs("Negative numbers have no natural logarithms\n", stderr);
- exit(1);
- }
- *(S3-1)=log(*S3);
- S3--;
- break;
- case 'F':
- *(S3-1)=sin(*S3);
- S3--;
- break;
- case 'G':
- *(S3-1)=cos(*S3);
- S3--;
- break;
- case 'H':
- if(*S3==3.1415926535897932/2)
- {
- fputs("The pi/2 has no tangent\n", stderr);
- exit(1);
- }
- *(S3-1)=tan(*S3);
- S3--;
- break;
- case 'I':
- *(S3-1)=asin(*S3);
- S3--;
- break;
- case 'J':
- *(S3-1)=acos(*S3);
- S3--;
- break;
- case 'K':
- *(S3-1)=atan(*S3);
- S3--;
- break;
- case 'L':
- *(S3-1)=(*S3)*3.1415926535897932/180.0;
- S3--;
- break;
- case 'M':
- *(S3-1)=fabs(*S3);
- S3--;
- break;
- case 'N':
- *(S3-1)=round(*S3);
- S3--;
- break;
- case 'O':
- *(S3-1)=floor(*S3);
- S3--;
- break;
- case 'P':
- *(S3-1)=ceil(*S3);
- S3--;
- break;
- case 'Q':
- *(S3-1)=exp(*S3);
- S3--;
- break;
- case 'R':
- *(S3-1)=sinh(*S3);
- S3--;
- break;
- case 'S':
- *(S3-1)=cosh(*S3);
- S3--;
- break;
- case 'T':
- *(S3-1)=tanh(*S3);
- S3--;
- break;
- case 'U':
- *(S3-1)=asinh(*S3);
- S3--;
- break;
- case 'V':
- *(S3-1)=acosh(*S3);
- S3--;
- break;
- case 'W':
- *(S3-1)=atanh(*S3);
- S3--;
- break;
- case 'X':
- *(S3-1)=(int)(*S3);
- S3--;
- break;
- case 'Y':
- if(*S3 <0)
- {
- fputs("Negative numbers have no factorial", stderr);
- exit(1);
- }
- *(S3-1)=tgamma(*S3);
- S3--;
- break;
- case 'Z':
- if(*S3 <0)
- {
- fputs("A negative number can not be used as a random upper bound", stderr);
- exit(1);
- }
- else if(*S3 <2)
- {
- *(S3-1)=rand() % 8192 /8192.0;
- }
- else
- {
- *(S3-1)=rand() % (int)(*S3);
- }
- S3--;
- break;
- case '+':
- *(S3-1)+=*S3;
- S3--;
- break;
- case '-':
- *(S3-1)-=*S3;
- S3--;
- break;
- case '*':
- *(S3-1)*=*S3;
- S3--;
- break;
- case '%':
- case '/':
- if(*S3 !=0)
- {
- if(*op=='%')
- {
- *(S3-1)=(int)*(S3-1) % (int)*S3;
- }
- else
- {
- *(S3-1)/=*S3;
- }
-
- }
- else
- {
- fputs("Divisor is zero error\n", stderr);
- exit(1);
- }
- S3--;
- break;
- case '|':
- *(S3-1) =(int)(*(S3-1)) | (int)(*S3);
- S3--;
- break;
- case '&':
- *(S3-1) =(int)(*(S3-1)) & (int)(*S3);
- S3--;
- break;
- case '^':
- if(*(S3-1)==0 && *S3<0)
- {
- fputs("Function pow's divisor is zero error\n", stderr);
- exit(1);
- }
- *(S3-1)=pow(*(S3-1), *S3);
- S3--;
- break;
- case '!':
- if(*S3 <0)
- {
- fputs("Negative numbers have no factorial\n", stderr);
- exit(1);
- }
- *S3=fact((long long)(*S3));
- break;
- default :
- di=0, ni=1;
- while('0'<=*op && *op<='9')
- {
- di=10*di+(*op)-'0';
- op++;
- }
- if(*op=='.')
- {
- op++;
- while('0'<=*op && *op<='9')
- {
- di=10*di+(*op)-'0';
- op++, ni*=10;
- }
- }
- *(++S3)=di/ni;
- break;
- }
- op++;
- }
-
- if (isinf(*S3)||isnan(*S3))
- {
- fputs("Overflow or illegal operation is calculated", stderr);
- exit(1);
- }
- return *S3;
- }
-
- //MAIN主函数入口
- int main(int argc, char** argv)
- {
- if ((argc==1) || (argc==2 && !strcasecmp(argv[1], "-h")))
- {
- fprintf(stderr, HELPINFORMATION);
- return 0;
- }
-
- int i = 2;
- char* prExp = NULL;
- if ((argc > 1) && (argv[1][0]=='-' && (argv[1][1]=='e' || argv[1][1]=='E')))
- {
- prExp = (argv[1][2] != '\0') ?(argv[1]+2) :((argc > 2)?(argv[i++]):NULL);
- }
-
- if (prExp == NULL)
- {
- fprintf(stderr, HELPINFORMATION);
- return 1;
- }
-
- srand((int)getpid());
- char prBuf[STACK_SIZE], *t=prBuf, *p=prExp;
- static char nowTime[128];
- static const char* timeFormatGMT = "%a, %d %b %Y %H:%M:%S";
-
- #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
- HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);
- WORD orgCOLOR;
- CONSOLE_SCREEN_BUFFER_INFO buffINFO;
- GetConsoleScreenBufferInfo(handle_out, &buffINFO);
- orgCOLOR=buffINFO.wAttributes;
- #endif
-
-
- while(*p)
- {
- if (*p == '\\')
- {
- t=prBuf;
- *t++ = '%';
- p++;
- while(*p=='+' || *p=='-' || *p=='0' || *p==' ' || *p=='#' || ('0'<=*p && *p<='9') || *p=='.')
- *t++ = *p++;
-
- switch (*p)
- {
- case 'n':
- printf("\n");
- break;
-
- case 'r':
- printf("\r");
- break;
-
- case 't':
- printf("\t");
- break;
-
- case 'T':
- {
- time_t timeNow = time((time_t*)0);
- strftime(nowTime, sizeof(nowTime), timeFormatGMT, (const struct tm*)localtime(&timeNow));
- printf("%s", nowTime);
- }
- break;
-
- #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
- case 'C':
- if(i >= argc)
- break;
- SetConsoleTextAttribute(handle_out, (int)RevPolishCore(argv[i++]));
- break;
- #endif
-
- case '\\':
- printf("\\");
- break;
-
- case ',':
- if(i >= argc)
- break;
- prThousandsformatted(argv[i++]);
- break;
-
- case 's':
- *t++ = *p;
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, (char*)argv[i++]);
- break;
-
- case 'c':
- *t++ = 'c';
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, (char)(int)RevPolishCore(argv[i++]));
- break;
-
- case 'd':
- *t++ = 'd';
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, (int)RevPolishCore(argv[i++]));
- break;
-
- case 'o':
- *t++ = 'o';
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, (int)RevPolishCore(argv[i++]));
- break;
-
- case 'e':
- case 'E':
- *t++ = *p;
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, RevPolishCore(argv[i++]));
- break;
-
- case 'g':
- case 'G':
- *t++ = *p;
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, RevPolishCore(argv[i++]));
- break;
-
- case 'x':
- case 'X':
- *t++ = *p;
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, (int)RevPolishCore(argv[i++]));
- break;
-
- case 'u':
- *t++ = 'u';
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, (unsigned int)RevPolishCore(argv[i++]));
- break;
-
- case 'f':
- *t++ = 'f';
- *t='\0';
- if(i >= argc)
- break;
- printf(prBuf, RevPolishCore(argv[i++]));
- break;
-
- default:
- fprintf(stderr, "Unknow flag '%c'", *p);
- return 1;
- }
- p++;
- }
-
- t=prBuf;
- while(*p && *p != '\\')
- *t++ = *p++;
-
- *t='\0';
- printf("%s", prBuf);
-
- if(i >= argc && argc!=2)
- break;
-
- }
-
- #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
- SetConsoleTextAttribute(handle_out, orgCOLOR);
- #endif
-
- return 0;
- }
复制代码
|