使用grep在匹配后提取第一个单词

时间:2013-03-29 23:09:49

标签: linux sed awk grep

我正在尝试从本机PHP中的所有脚本中提取所有MySQL查询。我希望仅使用grep从下面的查询中提取表名。以下是我的努力浪费在我的想法上。

FROM 'tablename'

FROM tablename

FROM apn.tablename

FROM apn.table_name

FROM 'apn.tablename'

grep -ionER "(FROM)[[:space:]](.*[a-zA-Z\d_.\`])[\s]"

重要的是grep捕获在表名结束后立即停止捕获文本,而我的grep没有。

我需要结果来显示这些信息:

(脚本位置):(行号):(表名)

/var/www/sites... : Line 31 : example_table_name

3 个答案:

答案 0 :(得分:2)

看起来后面会完成你想要的吗?

grep -P -i -o '(?<=from )\S+' *.php | sed -r 's/^\W|\W$//g'

更新

如果您还想要打印文件名和行号,您可能需要for循环:

for i in `grep -R --include=*.php -l -i 'FROM' /var/www/sites`; do grep -Pion '(?<=from )\S+' $i | sed -r -e "s/['\`\"]/ /g" -e 's#^#'$i'... : line #'; done

其工作原理如下:

  • 对于每个文件
    • grep递归,打印文件名,不区分大小写搜索FROM中的*.php
    • "from "后面查找非空格,仅打印行号和匹配单词
    • 使用sed'"`替换为空格,并在行的开头插入文件名

示例会话:

rojo@pico:~$ cat Desktop/test.php
' SELECT * FROM `contacts` WHERE 1=1' test data here that should be cut out'

rojo@pico:~$ for i in `grep -R --include=*.php -l -i 'FROM' .`; do grep -Pion '(?<=from )\S+' $i | sed -r -e "s/['\`\"]/ /g" -e 's#^#'$i'... : line #'; done
./Desktop/test.php... : line 1: contacts

以下是使用awk的另一种选择:

find /var/www/sites -type f -iname '*.php' -print0 | xargs -0 awk 'BEGIN {FS="from|FROM|where|WHERE"} {++x;} /from|FROM/ {printf "%s... : line %d : %s%s", FILENAME, x, $2, ORS}'

...但我还没弄明白如何让它围绕表名去掉引号/反引号/撇号。如果它很重要的话,我可能会通过sedtr来管它,但是必须有更优雅的方式来实现它。

答案 1 :(得分:2)

不要使用grep。这是Awk的量身定制的工作:

awk '$1 == "FROM" { print $2 }'

编辑感谢@rojo提供此建议

awk 'BEGIN{FS="from|FROM|where|WHERE"} /from|FROM/ {print $2}'

编辑2 :使用文件名和行#

awk 'BEGIN{FS="from|FROM|where|WHERE"}
      /from|FROM/ {printf ("%s:%d:%s\n", FILENAME, NR, $2)}'

答案 2 :(得分:0)

我尝试了以下这一行。它会以点,短划线和单引号为例,并拉出表名。您可以使用grep / gawk / sed部分并循环遍历PHP代码。


    echo "select * from 'the_db.the_table' where the_result=1;" | grep -ioE "(from)[[:space:]]([a-zA-Z0-9\_\.\']*)[[:space:]]" | gawk '{ print $2 }' | sed -e s/\'//g

    the_db.the_table