注:由于编码问题 \括弧 会被转义,因此本文中写成 \空格括弧
文本a.cfg大致如下:
"export": {
"table": [
{
"cb": "default",
"fn": "T_ORDER.csv",
"sql": "select f_order_no, f_inst_id from t_order where f_apply_date = '%s'",
"type": "1"
},
{
"cb": "default",
"fn": "T_MATCH.csv",
"sql": "select f_match_no, f_buy_or_sell, f_client_id, f_seat_id, f_inst_id, f_match_date, f_match_time, f_price, from t_match where f_match_date = '%s'",
"type": "1"
},
……
……
}
目的:cfg文本中有很多sql项,想要对数据库表进行select操作,我们想通过一个脚本处理得到所有被select的表名列表
注意到select ...... from+空格后面紧跟的就是表名,可以用正则表达式匹配得到
很快就能想到使用Python正则表达式中的“组”,匹配前面的select from内容,然后用“组”打印表名
fileContent=file("a.cfg").read()
re.findall(r"select.*from (\w+)", fileContent)
但是如果使用shell,应该如何完成相同的功能呢?
先尝试了grep,就算使用-o,也只是打印匹配到的key的内容,而不能打印匹配到内容的前后文,因此放弃。
后来注意到sed有相似的组\ (..\ ) 用法:
保存匹配的字符,如s/\ (love\ )able/\1rs,loveable被替换成lovers。
sed 's/keywords\ (pattern1\ )\ (pattern2\ )/\1\2/ #匹配keywords(pattern1)(pattern2),并将其替换为pattern2和pattern1匹配到的内容
于是开始尝试
1. sed 's/select.*from (\w+)/\1/' app_bac_tbl.cfg
报错:sed:-e 表达式 #1,字符 24:“s”命令的RHS非法引用\1。
原因:组匹配括弧前要加反斜杠\ (...\ ),修改后再次尝试
2. sed 's/select.*from \ (\w+\ )/\1/' app_bac_tbl.cfg
发现把整个cfg文件打印了一遍,于是使用sed -n 加上p的用法,修改后再次尝试
3. sed -n 's/select.*from \ (\w+\ )/\1/p' app_bac_tbl.cfg
发现什么都没打印,也就是什么都没匹配到
原因:sed中使用+表示匹配一次或多次时,前要加反斜杠\转移,否则sed会认为是要匹配字符'+',由于cfg的表名中没有+,自然就匹配不到,修改后再次尝试
4. sed -n 's/select.*from \ (\w\+\ )/\1/p' app_bac_tbl.cfg
发现它将匹配到并替换后的行打印出来了,例如:
"sql": "t_order where f_apply_date = '%s'",
"sql": "t_match where f_match_date = '%s'",
因为我们只想打印表名,那么就把行中表名以外的其它内容都匹配,然后替换成表名,修改后再次尝试
5. sed -n 's/.*select.*from \ (\w\+\ ).*$/\1/p' app_bac_tbl.cfg
得到我们想要的结果:
t_order
t_match
……
……
如果有其它更好用的方法,欢迎交流~