我想找到传递给项目中__()
函数的所有不同参数。到目前为止,我构建的最好的grep
电话就是这个:
find . -name "*.php" | xargs grep "__('.*')" -sioh
它成功找到对__()
函数的所有调用,但它有以下问题:
__()
函数调用,而不是仅打印参数我想要的是传递给函数的所有不同参数的列表,所以我希望每个参数都在它自己的行中(开头没有__(
而末尾没有)
)。
对于如下所示的示例行:
/* Some code */ __('foo'); /* Some more code */ __('bar'); /* Even more code */
我的命令返回以下结果:
__('foo'); /* Some more code */ __('bar')
我想得到的是(在没有引号的明显行中):
foo
bar
编辑:
事实证明,第一个参数并不总是单引号字符串。有时它是一个变量(以$
符号开头,因为它有问题的PHP,并且可选地有数组索引,例如$a['b']
)。
还有两个可选的布尔参数。但它只是我真正关心的第一个参数,其他两个并不重要。
答案 0 :(得分:4)
这个答案假设如下,符合OP后来的澄清:
- 输入数据中的__()
次调用有1-3个参数,不必须单引号。
- 只应提取第一个参数
- 第一个参数本身既不包含,
也不包含)
。
功能
尝试以下操作,这应该适用于大多数平台:
find . -name "*.php" -exec grep -sioh "__([^,)]*" {} + | cut -c 4-
-exec
的+
可确保尽可能少地执行grep
次调用(在大多数情况下,仅 1 ); {}
是匹配文件名的占位符。grep
正则表达式应该不那么贪婪,以确保捕获一行上的多个调用;此外,由于现在很清楚只应提取 1st 参数,[^,)]*
仅用于捕获下一个参数或右括号。 (请注意,如果第一个参数本身包含逗号或括号,则仍可能失败。)cut
命令会从grep
的输出中删除不需要的部分(剥离__(
前缀)。如果您的grep
实现支持-R
(用于递归搜索)和--include
(用于将搜索的文件限制为匹配glob的文件),您可以使用
grep -R --include '*.php' -sioh "__([^,)]*" . | cut -c 4-
如果您的grep
实施还支持-P
(PCRE:与Perl兼容的正则表达式),请使用anubhava's answer的修改版本:
grep -R --include '*.php' -siohP "__\(\K[^,)]*"
使用-P
可以更方便地通过附加前瞻断言((?=...)
)来使正则表达式更加健壮,以确保捕获的令牌确实后跟文字{{ 1}}或,
。
)
最后,请注意 grep -R --include '*.php' -siohP "__\(\K[^,)]*(?=[,)])"
grep
要求-P
与文字\(
匹配的方式,而上述非(
-P
命令基本正则表达式,其中grep
不特殊且被视为文字(在那里,您必须使用(
使它们变得特殊)。
在没有\(
的grep实现中,将grep调用为-P
或使用egrep
激活对扩展正则表达式的支持,这些正则表达式具有更多功能并且更接近于PCRE的语法,但功能不强。
关于便携性的说明:
-E
(支持PCRE == Perl兼容的正则表达式)是 GNU grep扩展(在BSD grep中不起作用)。-P
是(至少)GNU grep和BSD grep中的扩展名。-o
和-R
是(至少)GNU grep和BSD grep中的扩展名。答案 1 :(得分:2)
使用此grep -P
(PCRE):
grep -HoP '__\(\K[^)]*' *.php
file.php:'foo'
file.php:'bar'
找到__\(
,\K
重置匹配的数据。 [^)]*
然后在)
之前找到文字。
答案 2 :(得分:1)
这不如anubhava的答案好,但它更好,适用于没有PCRE标志的grep。
在匹配中使用[^)]*
而不是.*
将停止在函数末尾的匹配,而不是在该行的最后一个函数调用的结尾。
$ grep -sioh "__('[^)]*')" *.php
__('foo')
__('bar')