私はまだPerlを学んでいるので、明らかな質問であれば謝ります。 括弧で囲まれていないテキストと一致する方法はありますか? たとえば、fooを検索すると2行目と一致します。括弧で囲まれていない一致するテキスト
(bar foo bar)
bar foo (
bar foo
(bar) (foo)
)
私はまだPerlを学んでいるので、明らかな質問であれば謝ります。 括弧で囲まれていないテキストと一致する方法はありますか? たとえば、fooを検索すると2行目と一致します。括弧で囲まれていない一致するテキスト
(bar foo bar)
bar foo (
bar foo
(bar) (foo)
)
これは「明白」とは非常に遠く離れています。それどころか。複雑なパターンには「一致しない」と言う直接的な方法はありません(文字レベルでのサポートは[^a]
、\S
など)。正規表現はまず第一にマッチするものであり、マッチングしないものではありません。
1つのアプローチは、それらの(おそらくネストされた)区切り文字にマッチさせ、それ以外のすべてを取得することです。
ネストされたデリミタを見つけるための優れたツールは、コアモジュールText::Balancedです。一致すると、マッチの前の部分文字列とマッチ後の残りの文字列を与えることもできます。
use warnings;
use strict;
use feature 'say';
use Text::Balanced qw(extract_bracketed);
my $text = <<'END';
(bar foo bar)
bar foo (
bar foo
(bar) (foo)
)
END
my ($match, $before);
my $remainder = $text;
while (1) {
($match, $remainder, $before) = extract_bracketed($remainder, '(', '[^(]*');
print $before // $remainder;
last if not defined $match;
}
extract_bracketed
リターンマッチ、前サブストリング残り($remainder
)、およびサブストリング($before
)。私たちは残りの部分で一致を維持します。
this postより詳細と別の方法がありますが、Regexp::Commonを使用してください。
私はこのモジュールについて知らなかった。ありがとう!ところが、 '$ text'や' $ lead'の内部でマッチすると、行番号を見つけるのが難しいと感じています。 1つの方法は、 '$ match'で改行文字の数を数えることです。しかし、より良い方法がありますか? – Tohiko
@Tohikoようこそ。ソース内の文字/行が見つかりましたか? '$ lead'(または' $ text')の中で '\ n'を数えれば、ソースにある行は通知されません。私はそれを調べます。 – zdim
@Tohiko '$ lead'を' $ before'に、 '$ text'を' $ remainder'に変更しました。 – zdim
正規表現パターンの暗黙の先頭は\G(?s:.)*?
です(「一致するまで文字をスキップする」)。以下では、その定義を展開して、ネストされた括弧をスキップする文字にすることを検討します。
while (
$string =~ m{
\G (?&MEGA_DOT)*?
(foo)
(?(DEFINE)
(?<MEGA_DOT> [^()] | \((?&MEGA_DOT)*+ \))
)
}xg
) {
say "Found a match at pos $-[1].";
}
あなたは否定的な先読みを使用していますか? – Boschko