我有一個 C 檔案。使用 C 樣式的注釋集 /* */ 后跟為每個注釋定義的變數。變數名也在注釋中。一些注釋包含它們不用于的變數名稱(請參見下面示例中的第三條注釋)
以下是格式示例:
/* Object: function1: Does some really cool things and then it ends */
const function1 = someValue;
/* Object: function2: Does more really cool things and then it ends */
const function2 = someValue2;
/* Object: function3: Does even more really cool things
just like function2, does but continues over to the next line for a multiline comment */
const function3 = someValue3;
/* Object: function4: Does all kinds of cool things
and needs function1 in order to set a value correctly */
const function4 = someValue4;
/* Object: function5: Does some other cool things
and needs function2[with another variable] to do some things */
const function5 = someBValue5;
我只想將變數名稱與這樣的結果匹配:function1 function2 function3 function4 function5

這不是我的問題的完整答案,因為它沒有省略函式名前面的 const & 空格。函式 1、函式 2 等只是通用函式名稱。它們將是字母數字,因此相信 function[\w] 仍然為函式名稱提供了最佳捕獲。
uj5u.com熱心網友回復:
我對這個問題的看法:從注釋之外的定義(后跟=)中找到一個函式名稱,但在提到它的注釋之后(后跟:)。
這是一個簡單的、一步一步的全狀態方法:檢測我們是否在評論中,是否找到/(function[0-9] ):/,并設定合適的標志;然后在注釋和更新標志之后尋找相同的功能。
use warnings;
use strict;
use feature 'say';
my $file = shift // die "Usage: $0 filename\n";
open my $fh, '<', $file or die $!;
my (@func_names, $inside_comment, $func_name);
while (<$fh>) {
chomp;
# Are we inside a comment? Look for function[0-9] :
if (m{/\*}) { #/ fix syntax hilite
$inside_comment = 1 if not m{\*/}; #/ starts multiline comment?
if (/(function[0-9] ):/) {
$func_name = $1;
}
}
elsif (m{\*/}) { #/ closing line for multiline comment
$inside_comment = 0;
if (not $func_name and /(function[0-9] ):/) { #/
$func_name = $1;
}
}
elsif ($inside_comment and not $func_name) {
if (/(function[0-9] ):/) {
$func_name = $1;
}
}
# Check for name outside (after) a comment where it was found
elsif (not $inside_comment and $func_name) {
if (/(function[0-9] )\s =/) {
say "Found our definition: $1";
push @func_names, $1;
$func_name = '';
}
}
}
say for @func_names;
這將使用提供的樣本按預期列印。缺點:每行使用正則運算式測驗兩次。對于像源代碼這樣的小檔案,人們永遠不會注意到,但這并不好。可能有(邊緣?)未涵蓋的情況,?請測驗和改進。
另外一個選項。將整個檔案讀入一個字串,并通過注釋單步執行,檢查每個之后的函式名;或者,將其決議為注釋 函式定義。兩者都使用\G /g。
use warnings;
use strict;
use feature 'say';
die "Usage $0 filename\n" if not @ARGV;
my $cont = do { local $/; <> };
# Pattern inside a C-style comment, possibly multiline (NOTE: not general)
my $re_cc = qr{/\* .*? (function[0-9] ): .*? \*/}sx;
my @func_names;
while ($cont =~ /$re_cc\s*/gc) {
my $func_name = $1;
if ( $cont =~ /\G .*? (function[0-9] )\s*=/x and $func_name eq $1 ) {
push @func_names, $1;
}
}
請參閱錨\G及其與/g perlop中的修飾符結合使用。其他一些資源是這個頁面和這篇文章(還有更多)。
這做出了一些假設,也許更安全的版本是
use warnings;
use strict;
use feature 'say';
die "Usage $0 filename\n" if not @ARGV;
my $cont = do { local $/; <> };
# Pattern inside a C-style comment, possibly multiline (NOTE: not general)
my $re_cc = qr{/\* .*? (function[0-9] ): .*? \*/}sx;
my (@func_names, $func_name);
while (1) {
if ($cont =~ /\G $re_cc \s*/gcx) {
$func_name = $1;
}
elsif ($cont =~ /\G (function[0-9] )\s* = .*?\n\s*/gcx
and $func_name eq $1) {
#say "Found function definition for: $1 (at pos=", pos $cont, ")";
push @func_names, $1;
$func_name = '';
}
elsif ($cont =~ /\G \S \s*/gcx) { } # other, skip
else { last }
}
say for @func_names;
這些都正確處理提供的檔案,但對于更一般的情況肯定可以改進。?
請記住,一般和正確地識別 C 風格的注釋可能非常棘手。請參閱此 perldoc 常見問題解答
?一:如果評論后面沒有定義,我們的標志可能會處于錯誤狀態
? 雖然關于改進的注釋是關于它的一般操作,但這里是相關的正則運算式注釋。
該$re_cc模式使用/s修飾符來.匹配換行符,因為它必須.*匹配多行。但是,這種方式修飾符是全域設定的,它適用于使用此模式的正則運算式的其余部分!好吧,這可能不是故意的。
在這種情況下,我看不出它有什么關系,但萬一它可能有一種方法來設定一個嵌入的(模式匹配)修飾符,它只適用于模式
/(?s)pattern(?-s)/
或者,如果模式在其組內自然起作用,則修飾符將被洗掉,因此我們不需要取消它(?-s)
/((?s)pattern)/
uj5u.com熱心網友回復:
嘗試const用作過濾器:
"const (\bfunction[\w] \b[^:,])"
它不允許其他鄰居,為您提供函式名稱的唯一值。
為了獲得您的組,您需要參考\1并且您只會獲得函式名稱。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/464651.html
