我正在尋找一個正則運算式來匹配對可變引數 c 函式的所有潛在多行呼叫。最終目標是列印每個呼叫的檔案、行號和第四個引數,但不幸的是我還沒有。到目前為止,我有這個:
perl -ne 'print if s/^.*?(func1\s*\(([^\)\(,] ||,|\((?2)\))*\)).*?$/$1/s' test.c
與 test.c:
int main() {
func1( a, b, c, d);
func1( a, b,
c, d);
func1( func2(), b, c, d, e );
func1( func2(a), b, c, d, e );
return 1;
}
-- 與第二次通話不匹配。它不匹配的原因是s運算式末尾的 允許.匹配換行符,但似乎不允許[..]構造匹配換行符。我不知道如何克服這一點。
我也不確定如何在這個...中參考第四個引數... $2,$3不要在其中填充(即使他們這樣做了,我想由于正則運算式的遞回性質,我會遇到一些問題)。
uj5u.com熱心網友回復:
這應該可以捕獲您的功能,但需要注意
perl -0777 -wnE'@f = /(func1\s*\( [^;]* \))\s*;/xg; s/\s / /g, say for @f' tt.c
我使用陳述句必須以 . 結尾的事實;。然后,這排除了注釋中的意外;,并且排除了對嵌套在另一個呼叫中的 this 的呼叫。如果這是可能的,那么需要做更多的作業來決議它。
然而,進一步決議捕獲的呼叫(可能是逗號)由于嵌套呼叫很可能并且實際上包含逗號這一事實而變得復雜。怎么樣
func1( a, b, f2(a2, b2), c, f3(a3, b3), d );
這成為一個更有趣的小決議問題。或者,宏呢?
你能澄清一下哪些事情是不需要考慮的嗎?
由于提到的警告可能會被忽略,這里是一種使用 Text::Balanced決議引數串列的方法。
因為如果它們作為引數出現,我們需要提取整個函式呼叫,比如f(a, b),庫中最合適的函式是extract_tagged. 有了它,我們可以使開始標簽成為一個單詞左括號 ( \w \(),而結束標簽成為一個右括號\)。
這個函式只提取第一次出現的,所以它被包裹在extract_multiple
use warnings;
use strict;
use feature 'say';
use Text::Balanced qw(extract_multiple extract_tagged);
use Path::Tiny; # path(). for slurp
my $file = shift // die "Usage: $0 file-to-parse\n";
my @functions = path($file)->slurp =~ /( func1\( [^;]* \) );/xg;
s/\s / /g for @functions;
for my $func (@functions) {
my ($args) = $func =~ /func1\s*\(\s* (.*) \s*\)/x;
say $args;
my @parts = extract_multiple( $args, [ sub {
extract_tagged($args, '\\w \\(', '\\\)', '.*?(?=\w \()')
} ] );
my @arguments = grep { /\S/ } map { /\(/ ? $_ : split /\s*,\s*/ } @parts;
s/^\s*|\s*\z//g for @arguments;
say "\t$_" for @arguments;
}
回傳部分僅具有extract_multiple(嵌套)函式呼叫(可通過使用括號來識別),它們是它們所代表的引數以及我們所尋求的所有這些,以及具有逗號分隔的其他引陣列的字串的部分,它們被拆分為個別論據。
注意轉義量extract_tagged(通過反復試驗發現)!這是必需的,因為這些字串在字串中被兩次雙引號 - eval。這根本沒有記錄,所以請查看源代碼(例如此處)。
或者直接產生需要轉義的字符(\x5Cfor \),然后不需要轉義
extract_tagged($_[0], "\x5C".'w '."\x5C(", '\x5C)', '.*?(?=\w \()')
我不知道我會稱之為“更清晰”
我對問題中提供的檔案進行了測驗,我在其中添加了一個函式
func1(a, b, f2(a2, f3(a3, b3), b2), c, f4(a4, b4), d, e);
對于每個函式,程式都會列印帶有要決議的引數串列和決議的引數的字串,輸出中最有趣的部分是上述(添加的)函式
[ ... ]
a, b, f2(a2, f3(a3, b3), b2), c, f4(a4, b4), d, e
一個
b
f2(a2, f3(a3, b3), b2)
C
f4(a4, b4)
d
e
uj5u.com熱心網友回復:
不是 Perl,但可能更簡單:
$ cat >test2.c <<'EOD'
int main() {
func1( a, b, c, d1);
func1( a, b,
c, d2);
func1( func2(), "quotes\"),(", /*comments),(*/ g(b,
c), "d3", e );
func1( func2(a), b, c, d4(p,q,r), e );
func1( a, b, c, func2( func1(a,b,c,d5,e,f) ), g, h);
return 1;
}
EOD
$ cpp -D'func1(a,b,c,d,...)=SHOW(__FILE__,__LINE__,d,)' test2.c |
grep SHOW
SHOW("test2.c",2,d1);
SHOW("test2.c",3,d2)
SHOW("test2.c",5,"d3")
SHOW("test2.c",7,d4(p,q,r));
SHOW("test2.c",8,func2( SHOW("test2.c",8,d5) ));
$
如最后一行所示,如果函式可以將自身作為引數,則需要做更多的作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/506231.html
