grep用法

grep是一个常用的命令。
以前只知道^$.+?*这些用法。以及-E的正则表达式。

今天偶然发现还有一些更高级的匹配模式。具体如下:

[:alnum:]    字母与数字字符
[:alpha:]    字母
[:ascii:]    ASCII字符
[:blank:]    空格或制表符
[:cntrl:]    ASCII控制字符
[:digit:]    数字
[:graph:]    非控制,非空格字符
[:lower:]    小写字母
[:print:]    可打印字符
[:punct:]    标点符号字符
[:space:]    空白字符,包括垂直制表符
[:upper:]    大写字母
[:xdigit:]    十六进制数字

还有一些常用的就是
{n}            必须匹配n次
{n,}        必须匹配n次或n次以上
{n,m}        必须匹配n到m次,包含n和m

下面我们进行简单的测试下就知道了
文本内容如下test.txt

A novel is a book of long narrative in literary prose

The genre has historical roots both in the fields of the medieval and early modern romance and in the tradition of the novella

The latter supplied the present generic term in the late 18th century.

Further definition of the genre is historically difficult.

The construction of the narrative, the plot, the way reality is created in the works of fiction.

Most of these requirements were introduced in the 16th and 17th  centuries in order to give fiction a justification outside the field of  factual history.

The individualism of the presentation makes the  personal memoir and the autobiography the two closest relatives among  the genres of modern histories.
grep a[[:blank:]] test.txt

5561066808_a504984507_z.jpg

grep -E [a-z]\{10\} test.txt

5561066804_ae4c0ebe60_z.jpg

grep Th.[[:space:]] test.txt

5561066798_fb5625ab54_z.jpg

###########################################

Best regards
Timo Seven
blog:http://www.timoseven.com
twitter: http://twitter.com/zauc
Linux System Admin  & MySQL DBA

Advertisements

一个分析安居客最新房价的shell脚本

为了能够得到最新的房屋价格,虽然安居客这种网站的价格并不是很准,但是一旦有了历史数据,那分析起来还是可以得到点相关的信息的。分析的结果如下展示:

http://beijing.anjuke.com/viewprop-act-sell-id-34033853.html 13366569581 南北 美联物业 亚运新新家园朗月园 1450万元 5室3厅 365平米 39726元 共3层 2008
http://beijing.anjuke.com/viewprop-act-sell-id-34033627.html 13161862633 南北 润万嘉 远洋·万和城 760万元 3室1厅 163平米 46626元 8/12 2005 

第一列为房子的具体链接地址,第2列为销售的手机号,第3列为房子的朝向,第4列为中介公司,第5列为楼盘名字,第6列为总价,第七列为户型,第8列为楼层,第9列为房子年代

具体的shell脚本如下,得到的最后csv文件可以用excel或者python matlab进行画图。

#!/bin/bash
cd /home/timo/house

day=`date +%F-%H:%M`
today=`date +%F`
wget --header="Host: beijing.anjuke.com" --user-agent=Mozilla/5.0 http://203.166.162.82/v2/sale/W0QQdsmZmmQQmodeZ1QQs5Zall -O anjuke.txt

grep "房龄\|viewprop-act-sell-id" anjuke.txt | grep -v option > result.txt

sed '{N;s/\n/ /}' -i result.txt

if [ ! -f today.anjuke.$today.csv ] ;
then
	touch today.anjuke.$today.csv
fi

templink=`awk -F'"' '{print $2}' result.txt | tail -n 1`
tempid=`grep -c "$templink" today.anjuke.$today.csv`

if [ $tempid -le 0 ] ;  then
	echo "$day" >> today.anjuke.$today.csv
	awk '{print $2,$3,$11}' result.txt  | awk -F'"' '{print $2,$4,$5}' | sed 's#<em>\|</em>\|,\|单价:\|楼层:\|房龄:# #g' | sort -k 5 &gt;&gt; today.anjuke.$today.csv
fi

sed -e 's#二手房# #g' -i today.anjuke.$today.csv


for linenum in {1..25}
do
temp_phone=`awk '{print $2}' today.anjuke.$today.csv | tail -n 25 |  sed -n "$linenum"p| egrep "^[0-9]+" | wc -l`
if [ $temp_phone -le 0 ] ;
then
	for x in `awk '{print $1}' today.anjuke.$today.csv | tail -n 25 | sed -n "$linenum"p`
	do
		wget --user-agent=Mozilla/5.0 $x -O phone.txt
		phone=`egrep -e '"telphone"&gt;[0-9]+' phone.txt  | sed -e 's#<div class="telphone">\|</div>\|\t##g'`
		orien=`grep '朝向'  phone.txt  | grep -w li | sed -r 's#[a-z]||"|\/|=|\t|朝向:##g'`
		shop=`grep 'images.anjukestatic.com/broker' phone.txt  | awk -F'"' '{print $12}' | awk '{print $1}'`
		sed -e "s#$x#$x $phone $orien $shop#g" -i today.anjuke.$today.csv
	done
fi
done

计算所有房子总价的平均价格,不算不知道,一算吓我一跳阿

awk 'NF > 10' today.anjuke.2010-08-24.csv | awk '{print $6}' | awk -F'万元' '{print $1}' | awk 'BEGIN {sum=0} {sum+=$0} END{print sum/FNR}'
283.187

好了,其它的也就依样画葫芦计算拉。发现awk太强大了。

###########################################

Best regards
Timo Seven
blog: http://www.timoseven.com
twitter: http://twitter.com/zauc
Linux System Admin & MySQL DBA

使用gnu date来获取各种时间

由于运营需求,我经常在工作中需要写各种脚本来获取不同的时间,而我又不怎么喜欢使用mysql自带的时间函数,总觉得gnu date更强大一点,万全可以拼凑出我需要的时间格式。

比如要获取昨天的日期

date -d -1days +%F

这样一个简单的命令就可以获取昨天的日期,当然也可以随便之前之后多少天,而且我也不需要考虑闰月啊等等。

有时候运营想知道上周总的数据。那我们就寻要获取上周一到上周日的时间,那其实很简单

date -d 'last mon' +%F

也可以写全为,因为有时候你要写上个月就要写全为last month

date -d'last monday' +%F

那上周日很容易就是

date -d 'last sunday' +%F

那要取上个月呢?

date -d 'last month' +%Y-%m

取上一年

date -d 'last year' +%Y

大家也许都看到了我这里主要用的就是-d参数
在man date里关于-d的解释是这样的

-d, --date=STRING
显示由 STRING 指定的时间, 而不是当前时间

那这里的STRING到底有哪些选择呢?

查了下官方文档http://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html

发现主要有以下几种选择,一个是day, week, month, year这些选择。 另外一个是周一到周日的选择。
同时它还支持这几种条件的合集,比如,我要知道三周后多1天是几号:

date -d '3 week 1 day'

Best regards
Timo Seven
blog: http://www.timoseven.com
#####请翻墙浏览,或者指定hosts到74.200.243.252#######
twitter: http://twitter.com/zauc

Linux System Admin & MySQL DBA

shell常用资料(备查)

While的使用

while read line
do
       mysql ab -e "insert into filter values (null,'$line','xxxxxxxx','xxxxxxxx',1,8,1,1,188,'abc')"
done = '"$sunday"%' and time >files/blog_we
ek_num
                done
   fi
  done

上面做了2次for语句,第一次表示i从1-7,而第二次a是从1-99.上面第一个for语句是为了查询今天是否为星期天而产生的。

一个用shell完成的统计程序

要是shell里能进行很好的循环就好了。以及shell最不容易控制的就是’,”,`这3个标点符号的区别。`这个倒是比较简单,就是在shell里只是表示运行外部程序。”和’这个如果单独使用是没有任何问题的,但是一旦要配合使用就区分起来十分麻烦。

这个日志统计程序中总共用了500多行,先定义30个日期。这个要是能用循环就非常简单了。但是我还是用比较傻的一个个来进行定义。


day=`date -d -1days +%F`

 day_1=`date -d -2days +%F`

这里要是能够使用的数组来进行定义就非常简单了。


for i in {2..30}

do

eval day_$i=`date -d -"$i"days +%F`

eval echo \$day_$i

done

 

通过上面就可以进行循环定义了。

这里需要定义和引用变量的过程比较多,一个数据往往要转换多次才可以得到最后真实的数据,这里一共进行了4次数据的赋值工作加一次if判断工作。还好现在总的执行时间还在0.02秒以内完成。不然就必须得修改这样一个程序了。


login_user=`mysql -h$db -u$dbuser -p$dbpass -e "select distinct id from test.iplog where time like '"$day"%'" |sed -n '2,$'p > login_user.diff`

这个是用来统计今天有哪些用户登陆过了系统,并把结果写入到login_user.diff中


reg_30_user=`mysql -h$db -u$dbuser -p$dbpass -e "select id from test.user_desc where registertime like '"$day_30"%'" | sed -n '2,$'p > reg_30_user.diff && cat login_user.diff >> reg_30_user.diff`

这里在数据库中进行一次like操作,这个其实是很费时间的如果条数过多的话。查询出来通过sed来取出用户名到一个文件中同时跟今天的登录用户名进行合并。


login_user_number=`mysql -h$db -u$dbuser -p$dbpass -e "select count(distinct id) from test.iplog where time like '"$day"%'" | sed -n '2'p`

这个是用来统计今天登陆过系统的用户数。


num_30_reg=`cat reg_30_user.diff | sort | uniq -d | wc -l`

这个用来统计前面第30天注册的用户在今天到底有多少人登陆了。这个其实是可以跟上面这个语句进行合并的,但是怎么都测试不通过。也考虑过用select in操作来进行,首先是要进行行列转换


uniq_30_user=`mysql -h$db -u$dbuser -p$dbpass -e "select count(distinct id) from test.user_desc where registertime like  '"$day_30"%'" | sed -n '2'p`

计算那天的注册用户数量。这样根据前面2个数据可以知道注册用户的实际登陆频率是怎么样的。


if  [ $uniq_30_user -eq 0 -o $num_30_reg -eq 0 ];

then

per_30=0.00

else

per_30=`awk 'BEGIN {x='"$num_30_reg"';y='"$uniq_30_user"';printf "%.2f\n",x/y}'`

echo $per_30

fi;

首先是判断过去某一天的注册用户数是否为0,以及那天的注册用户在今天登陆数是否0,在shell中,除法的两边都不能为0,这个还跟普通的公式不同。如果2个数都为0,那直接赋值0.00给它,不然就进行除法运算,并保留2位小数。这个表达式的单引号双引号可是困惑了整整一天时间。

最后就是mysql插入的语句,把这30个数据最后按照一定的规律插入到表中就可以了。