今天在linux下写了个小程序,功能是:利用ps来查找包含当前字符串的所有命令,有时候会得到很多搜索结果,而且由于每个命令附带的参数很长,导致很乱很难以分清楚,下面这个程序会将匹配得到的结果每隔一行输出,而且搜索词会以红色加粗显示,并且搜索结果会被两条彩色线条分隔出来,该彩色线条的颜色和线型也都是随机变换的,这么做的目的是为了防止在一屏内的两次结果的四条线之间混乱,用不同颜色和线型加以区分会非常清晰明了,而且该彩色线条的长度是与你的终端宽度相匹配的;后续又改进了一下,比如你搜索mps Sh,那么可以为你搜索出mps SH;mps sh; mps sH; mps Sh四种结果的并集。
先看一下shell版本的:
#!/bin/bash
if [ "$#" -ne "1" ];then
echo "Usage: my <SearchWord>"
exit 1
fi
COLORTYPE=$((32+RANDOM%5))
lineArray=('=' '-' '#' '%' '~' '/')
LINETYPE=${lineArray[$((RANDOM%6))]}
echo -e "\033[1;${COLORTYPE}m`python -c "print ""'"${LINETYPE}"'"*$(echo $(stty size) | cut -d' ' -f2)`\033[0m"
echo
ps aux | grep -i $1 | awk "!/grep/&&!/mps.*$1/&&!/sed.*$1.*1;31m.*g/{print \$0 \"\n\" }" | sed -e "s/\($1\)/$(echo -e '\033')\[1;31m\1$(echo -e '\033')\[0m/gi"
#需要说明的是,上面的$(echo -e '\033')完全可以由字符^[,注意这是一个字符,表示Esc那个键,在vi里可以通过Ctrl+v,然后再按Esc来输入该特殊字符;这里用echo这么恶心的做法只是因为我如果写^[这个字符,怕误导大家以为是两个字符,因此给出了一个通用的,不会有歧义的,但是也很丑陋的做法
echo -e "\033[1;${COLORTYPE}m`python -c "print ""'"${LINETYPE}"'"*$(echo $(stty size) | cut -d' ' -f2)`\033[0m"
再给出c++版本的(其实上面的shell版本已经足够了,不过当初我没把shell实现的那么完整,后来才发现原来shell都可以实现之,因此下面的 c++版本纯粹是为了自我留念之用,大家可以不必看了,呵呵):
#include <termio.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <string>
#include <time.h>
using namespace std;
enum Color
{
GREEN = 32,
YELLOW = 33,
BLUE = 34,
MAUVE = 35,
CYANINE = 36
};
enum LineStyle
{
EQUAL = (uint32_t) '=',
TILDE = (uint32_t) '~',
ASTERISK = (uint32_t) '*',
MINUS = (uint32_t) '-',
POUND = (uint32_t) '#',
SLASH = (uint32_t) '/'
};
uint32_t ChooseColor()
{
srand(static_cast<unsigned>(time(0)));
switch(rand()%5)
{
case 0:
return GREEN;
break;
case 1:
return YELLOW;
break;
case 2:
return BLUE;
break;
case 3:
return MAUVE;
break;
default:
return CYANINE;
break;
}
return GREEN;
}
uint32_t ChooseLineStyle()
{
srand(static_cast<unsigned>(time(0)));
switch(rand()%6)
{
case 0:
return EQUAL;
break;
case 1:
return TILDE;
break;
case 2:
return ASTERISK;
break;
case 3:
return MINUS;
break;
case 4:
return POUND;
break;
default:
return SLASH;
break;
}
return EQUAL;
}
int main(int argc, char* argv[])
{
if (2 != argc)
{
cout << "Usage: mps <SearchWord>" << endl;
return 1;
}
struct winsize wsz;
ioctl(STDOUT_FILENO, TIOCGWINSZ, (char*) &wsz);
stringstream seperatorLine;
seperatorLine << "echo """ << (char)27 << "[1;" << ChooseColor() << 'm'
<< string("").append(wsz.ws_col, (char)ChooseLineStyle()) << char(27) << "[0m""";
char psCommand[1024] = {0};
sprintf(psCommand,"ps aux | grep %s | grep -v grep | grep -v 'mps.*%s' | grep -v 'sed.*%s.*""[1;31m%s.*g' | "
"awk '{print $0 """"n""}' | sed ""s/%s/%c""[1;31m%s%c""[0m/g""",
argv[1], argv[1], argv[1], argv[1], argv[1], (char)27, argv[1], (char)27);
system(seperatorLine.str().c_str());
system("echo");
system(psCommand);
system(seperatorLine.str().c_str());
return 0;
}
最后给出使用方法,不论是shell版本的还是binary版本的,都需要其有可执行权限,我是将其拷贝到/usr/bin目录下了,这样大家就都可以使用该程序了:mps vmware即可; 后来又想到更简单的办法,直接在.bashrc中定义个函数叫mps即可,把上面的shell代码copy到函数体里面(将exit 1换为return)就ok了。