• 締切済み

正規表現について教えてください

正規表現について教えてください。 「①:②:③:④」コロンで区切られた文字列があります。 コロンで区切られた文字列から各コロン間にある文字列を 条件に一致したものを取り出したいのですが 例:①:②:③:④ A000::: :01::: ::AA:: :::BB B001:A1:: B002:99:: C000::ABC01: C000:::BBB01 のように、①②③④の書き方は自由で、最低どこか一つに書かれていて、 ③と④は、両方同時にかかれません。 ここで、③と④のどちらかに入っているのをとりだしたいのですが、 どのように書けばよいでしょうか。 「'.*:.*:[^|:].*:[^|:].*'」としたらダメでした。 「'.*:.*:[^].*:[^].*'」でとりだせたのですが、正しい表現でしょうか。 また、指定したもの、③と④で、 例えば、Aで始まっている、Bで始まっているを 取り出したいのですが上手くいきません。 '.*:.*:[^](A|B).*.*:[^](A|B).*' '.*:.*:[^].*(A|B).*.*:[^].*(A|B).*' '.*:.*:(A|B)[^(A|B)].*:(A|B)[^(A|B)].*' としてみたのですが、表示されません。 お願いします。

みんなの回答

  • asciiz
  • ベストアンサー率70% (6809/9681)
回答No.6

>「[^]」をするこにより上手くいったのでしょうか。 私は、「[^]」が指しているものがわかりません。 正規表現の [ ] は、文字集合を作る命令です。 [ABCD] ならば、「A・B・C・Dのどれか」です。 そして、各括弧内側の最初に ^ を書くと、否定の意味になります。 [^ABCD] ならば、「A・B・C・D以外の任意の文字」です。 しかしその否定するものが空というのは? [^] がどんな文字にマッチするのか、わかりません。 従って、「'.*:.*:[^].*:[^].*'」というパターンが正しいものなのか、どこにどうマッチしているのか、理解できません。 自分では使おうとも思いませんし、すみませんが解説できません。

abc999xyz
質問者

お礼

いいえ、とんでもございまません。 動きがわかるようでしたらなので、 今まで、親切に説明していただきありがとうございます。 たいへん勉強になりました。

  • asciiz
  • ベストアンサー率70% (6809/9681)
回答No.5

>3番目と4番目にあるものを表示したい。 >3番目と4番目は同時には存在しない。 この条件は、『「3番目に値があり、4番目に無い」または「4番目に値があり、3番目に無い」』でいいですか? 正規表現「[0-9A-F]*」は、「16進数文字の0文字以上の文字列」を表せます。 正規表現「[0-9A-F]+」は、「16進数文字の1文字以上の文字列」を表せます。 そうすると、 「4番目に値があり、3番目に無い」は「[0-9A-F]*:[0-9A-F]*::[0-9A-F]+」と表せます。 しかし 「3番目に値があり、4番目に無い」は「[0-9A-F]*:[0-9A-F]*:[0-9A-F]+:」と表せ…そうですが、これはいけません。 最後のコロンの後に何か文字があってもマッチしてしまいますし、それが16進数だったとしてもひっかけてしまいます。 そこで行末記号を使います。 「3番目に値があり、4番目は無く行末である」が「[0-9A-F]*:[0-9A-F]*:[0-9A-F]+:$」と表せます。 この2つを合わせると、 [0-9A-F]*:[0-9A-F]*:(:[0-9A-F]+|[0-9A-F]+:)$ というパターンが考えられます。 検索したい文字列以外に文字が続いてるとまた困るのですけれど?

abc999xyz
質問者

お礼

ありがとうございます。 期待した結果となりました。 最初の質問でかいたのですが、 「'.*:.*:[^].*:[^].*'」としたら今回教えていただいたのと 同じ表示が得られました。 「.*」を使うのは横に置いておくとして、 「[^]」をするこにより上手くいったのでしょうか。

  • asciiz
  • ベストアンサー率70% (6809/9681)
回答No.4

>「[^:]*:[^:]*:[^:]*:[^:]*」 >だとすべて表示されます。 これはまず「4パートがコロンで区切られている」という基本パターンを示したものですから、全てのそういうパターンに引っかかって当然です。 この基本形を変形していって、『「3つめの先頭がAまたはBである」または「4つめの先頭がAまたはBである」』と言う限定検索にしたのが、回答No.1の最後だったわけです。 で、すみませんが >また、Aで始まっている、Bで始まっているものではなく >③と④のどちらかに入っているのをとりだしたい方ですが、 これの意味するところがちょっとわかりません?? 両方に入っている場合は除きたい、って事ですか? それとも 「::A:」 または 「:::B」 みたいなパターンだけ取り出したいって事ですか?

abc999xyz
質問者

補足

説明があいまいですみません。 A000:: :01:: ::AA: :::BB ::CC1: :::CC1 B001:A1:: B002:99:: C000::ABC01: C000:::BBB01 D000::D1: D000:::D2 から ::AA: :::BB ::CC1: :::CC1 :99:CC2: C000::ABC01: C000:::BBB01 D000::D1: D000:::D2 のような、3番目と4番目にあるものを表示したい。 3番目と4番目は同時には存在しない。

  • asciiz
  • ベストアンサー率70% (6809/9681)
回答No.3

>③の位置のものは引っ掛かりませんでした。 ではそもそも、or条件にする前のもの、 >[0-9A-F]*:[0-9A-F]*:[AB][0-9A-F]*:[0-9A-F]* これで③位置にあるものがちゃんと出てくるかどうか? 出ない場合、データ自体の不整合も疑いたくなってきます。(コロンが全角になってしまっているとか、うっかりセミコロンで区切られているとか。どの区切りのコロンが間違っていても、引っかからなくなります)

abc999xyz
質問者

補足

ありがとうございます。 すみませんでした。 条件と文字列が一致していませんでした。 条件にあった文字列で上手くいきました。 また、Aで始まっている、Bで始まっているものではなく ③と④のどちらかに入っているのをとりだしたい方ですが、 「[^:]*:[^:]*:[^:]*:[^:]*」 だとすべて表示されます。 こちらも、or条件にすればよろしいのでしょうか。

  • asciiz
  • ベストアンサー率70% (6809/9681)
回答No.2

> [0-9A-F]*:[0-9A-F]*:([AB][0-9A-F]*:[0-9A-F]*|[0-9A-F]*:[AB][0-9A-F]*) > だと、④位置書かれていいるもが表示されます。 > ③位置に書かれているものが表示されません。 この書き方が通ってるなら③位置のものに引っかからないのは変な気がしますが… カッコの中を逆順に書いた時どうなりますか? ↓ > [0-9A-F]*:[0-9A-F]*:([0-9A-F]*:[AB][0-9A-F]*|[AB][0-9A-F]*:[0-9A-F]*)

abc999xyz
質問者

補足

ありがとうございます。 > [0-9A-F]*:[0-9A-F]*:([0-9A-F]*:[AB][0-9A-F]*|[AB][0-9A-F]*:[0-9A-F]*) ③の位置のものは引っ掛かりませんでした。

  • asciiz
  • ベストアンサー率70% (6809/9681)
回答No.1

安易に「.*」を使ってはいけません。 それひとつ指定してしまったら、一行全体にマッチしてしまいます。 さらに、複数個所に「.*」を使うのは厳禁です。(書けてしまいますが、自主的に禁止した方が良いです) そのマッチ結果は不定となり、どの「.*」の部分にどれだけの文字列がマッチするか、処理系により異なることがあり得ます。(大概は、一番最初の .* が一番長くマッチするものですが。) 私だったら、こうしますかね。 [^:]*:[^:]*:[^:]*:[^:]* 「[^:]」 は、「コロン以外のすべての文字集合」です。 それに*を付けることで、「[^:]*」はコロン以外で構成された0文字以上の文字列を表します。 それが4つあり、上記のパターンは、それがコロンで区切られたもの、にマッチします。 ただしIPv6文字列を分割するなら、文字種は制限した方が良いかもしれません。 前記のマッチ文字列では、「ABCD:EFGH:あいうえお:かきくけこ test」 にもマッチしますし、前後にも文字がある場合、一番目・四番目部分にそこまで含まれてしまいます。(←この例では4番目は「かきくけこ test」までマッチしている) 16進数文字列に制限するなら、例えばこういうパターンが考えられます。 [0-9A-F]*:[0-9A-F]*:[0-9A-F]*:[0-9A-F]* 3番目・4番目がAまたはBで始まる、のは [0-9A-F]*:[0-9A-F]*:[AB][0-9A-F]*:[0-9A-F]* …3番目がAまたはBで始まる [0-9A-F]*:[0-9A-F]*:[0-9A-F]*:[AB][0-9A-F]* …4番目がAまたはBで始まる という感じにすればいいでしょうか。 ただ、 [0-9A-F]*:[0-9A-F]*:[AB][0-9A-F]*:[AB][0-9A-F]* と書いてしまうとこれは、「3番目および4番目の両方がAまたはBで始まる」ものにしかマッチしません。 それはあなたの希望に合っているでしょうか? 「3番目または4番目がAまたはBで始まる」を書きたいなら、例えばこんな風になるでしょう。 [0-9A-F]*:[0-9A-F]*:([AB][0-9A-F]*:[0-9A-F]*|[0-9A-F]*:[AB][0-9A-F]*) ※テストしてないのでうまく動かなかったらゴメンナサイ ※※もっと効率的な書き方があるかもしれません。

abc999xyz
質問者

補足

ありがとうございます。 期待する結果としては、 ::AA: :::BB C000::ABC01: C000:::BBB01 が欲しいです。 ③位置か④位置にあるもです。 試してみたのですが、 [^:]*:[^:]*:[^:]*:[^:]* だと、すべて表示されます。 [0-9A-F]*:[0-9A-F]*:([AB][0-9A-F]*:[0-9A-F]*|[0-9A-F]*:[AB][0-9A-F]*) だと、④位置書かれていいるもが表示されます。 ③位置に書かれているものが表示されません。

関連するQ&A