dポイントプレゼントキャンペーン実施中!

ちょうどn文字の連続にマッチする正規表現を教えて下さい。
https://perldoc.jp/docs/perl/5.16.1/perlreref.pod
こちらにある正規表現の文法は全て使用可能です。

例えば、
abbcccddeeeeeff
という文字列に対して、丁度2文字であれば、「bb」「dd」「ff」のみ検索されるようなものです。

失敗例: (.)\1(?!\1)

検索の仕組み上、不可能でしょうか?
先頭から順に、
abbcccddeeeeeff
bbcccddeeeeeff
bcccddeeeeeff
cccddeeeeeff
ccddeeeeeff
cddeeeeeff
ddeeeeeff
deeeeeff
eeeeeff
eeeeff
eeeff
eeff
eff
ff
f
という風に検索されていくのだと思ってますが、この仕組みだと、頭の文字の前に同じ文字があるかどうかを認識するのは不可能ですからね…

質問者からの補足コメント

  • 検索の仕組み上、直前一文字は必須なので、(2文字の連続は)
    (.)(?!\1)(.)\2(?!\2)|^(.)\3(?!\3)
    これで妥協できそうです。

      補足日時:2020/05/03 11:23

A 回答 (3件)

例えば


aabbccdd
に対して「aa」「bb」「cc」「dd」の全部を取り出そうとすると, それではうまくいかないんじゃないかな. というか, その条件だと
素直な正規表現ではどうやってもダメ
のような気すらする.

ということもあってズルいことをしたんだけど, 「2文字」という条件なら split と grep を組合せた方が見通しはよかったかもしれない.
    • good
    • 0
この回答へのお礼

諦めます。

お礼日時:2020/05/03 23:17

例えば



my $str = "abbcccddeeeeeff2;
my %doubles;
() = $str =~ /((.)\2++)(??{($doubles{$1}++ if length($1)==2)})/g;

ってやると key %doubles は "bb", "dd", "ff" になる... けどこの辺が限界かなぁって気はする.
    • good
    • 0
この回答へのお礼

なるほど笑笑
それはちょっとズルいですね笑
しかし、ありがとうございました。

従来からの静的な正規表現で後方の参照が前方で出来ない限り無理なのでしょうね。。

お礼日時:2020/05/03 11:04

それで合ってると思います。


あとは、それを取り出す言語側の記述ですね。
Perlで、「すべて取り出す」という記述が分からなかったので、RubyとPerlで。

Ruby
text = "abbcccddeeeeeff"
result = text.scan(/((.)\2)(?!\2)/).map(&:first)

Python
result = [x[0] for x in re.findall(r"((.)\2)(?!\2)",text)]

いずれも、括弧があると「マッチした物全体」じゃなくて括弧内しか抽出できないので、欲しい部分をさらに括弧で囲みます。
["bb","b"]と取り出されるので先頭要素を取ります。

「マッチした物全体を文字列からすべて取り出す」という機能のある言語なら、(.)\1(?!\1) のままでOKです。
    • good
    • 0
この回答へのお礼

どちらの言語でも、cc や ee も抽出されてしまいますね…

お礼日時:2020/05/03 10:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!