• ベストアンサー

perlでの括弧対応チェック

perlで括弧の対応の妥当性を知りたいのですが どの様にすればよろしいでしょうか? ex). (X1+X2)+X3 -> OK ((X1+X2)+X3 -> NG ((X1+X2))+X3 -> OK )(X1+X2)+X3 -> NG などチェックを行いたいと思っています

  • Perl
  • 回答数3
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • ryu_chan
  • ベストアンサー率37% (69/186)
回答No.3

Perl 5.10から正規表現に(?PARNO)という再帰する構文が加わりました。 その説明文に、まさに括弧対応の正規表現の例文があります。 http://fleur.hio.jp/perldoc/mix/pod/perl5100delta.mix.html#Regular_expressions これをそのまま流用すれば、以下のようなコードが書けます。 my @expressions = qw{ (X1+X2)+X3 ((X1+X2)+X3 ((X1+X2))+X3 )(X1+X2)+X3 }; for my $exp (@expressions) { print "$exp -> ", has_balanced_brackets($exp) ? 'OK' : 'NG', "\n"; } sub has_balanced_brackets { my $exp = shift; my $re = qr{ ^[^()]* # start of line ( # start capture buffer 1 \( # match an opening round bracket (?: # match one of: (?> # don't backtrack over the inside of this group [^()]+ # one or more non round brackets ) # end non backtracking group | # ... or ... (?1) # recurse to bracket 1 and try it again )* # 0 or more times. \) # match a closing round bracket ) # end capture buffer one }x; $exp =~ $re ? 1 : return; } あるいは、文字列の先頭から1文字ずつ括弧を探し、開き括弧と閉じ括弧の数が同じかをチェックする方法はどうでしょうか? とりあえず、質問者さん提示の例ではうまく動作しているようです。 sub has_balanced_brackets { my $exp = shift; my $bracket_count = 0; for my $pos ( 0 .. length($exp)-1 ) { my $char = substr $exp, $pos, 1; if ( $char eq '(' ) { $bracket_count++ } elsif ( $char eq ')' ) { $bracket_count-- } last if $bracket_count < 0; } $bracket_count == 0 ? 1 : return; }

barbarian1
質問者

お礼

大変参考になりました。 親切なご回答ありがとうございます。

その他の回答 (2)

  • zxcv0000
  • ベストアンサー率56% (111/196)
回答No.2

CPU負荷(処理時間)を気にするとかなり難しいテーマになます。 「\(」や "" で囲まれた括弧は括弧で無いなんていう規則を付けても、やはり難しいテーマになります。 そうで無ければ、例えば、最も内側の () の組を可能な限り繰り返し削除した結果に 「(」か「)」を含めば NG 無ければ OK とすれば良いです。 最も内側の () の組を 1個削除するのは s/\([^\(\)]*\)//s で良いでしょう。 これをヒントにやってみてください。 禁止事項である課題の丸投げの疑いがあるので、完成コードは書きません。 追加質問は、どこまでできていて何が分らないのかを詳しく書いてください。

barbarian1
質問者

お礼

大変参考になりました。 ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

Perl のバージョンにもよるけど, かっこの対応だけなら例えば my $reg; $reg = qr/([^()] # not parentheses | # or \((??{$reg})\) # proper parentheses )+/x; のような「正規表現」でチェックできると思う. 「連続しちゃだめ」とかいうことだともっと工夫しないといけません.

barbarian1
質問者

お礼

ありがとうございます。 おかげさまで何とかなりました。

関連するQ&A

  • 演算子と括弧

    perlで以下の事をやりたいのですが、いい方法が浮かびません。 文字列に含まれる括弧のそばに演算子が 無い場合はエラー(NG)にしたいのですが、 いい方法は無いでしょうか "あ(" が含まれる場合はNG "a(" が含まれる場合はNG "*(" が含まれる場合はOK "+(" が含まれる場合はOK "((" が含まれる場合はOK ")(" が含まれる場合はNG "("だけ が含まれる場合はOK 環境: SunOS 5.8 perl5 eucのみです

    • ベストアンサー
    • Perl
  • vimの括弧チェックを停止する方法

    vimの括弧チェックを停止する方法 入力モードで、丸括弧 "(" を入力すると、それよりも下の行にある波括弧 "{ }" が、 全て赤くハイライトされた状態となります。 対応する丸括弧 ")" を入力すると、元に戻ります。 おそらく、括弧の対応をチェックする機能だと思うのですが、 停止する方法が分かりません。 下記は、既に設定済みです。 set noshowmatch let loaded_matchparen=1 お手数ですが、必要な設定をお教え下さい。 よろしくお願いいたします。

  • サブルーチンやif分以外での中括弧

    perlについて学習中で、現在フリーのスクリプトを見て勉強しております。 中括弧の使い方を教えて欲しいです。 sub test { print"OK"; } if ($test>1) { print"OK"; }else{ print"NG";} 上記のようにサブルーチンやif文での使い方は分かるのですが、フリーのスクリプトの中に単に中括弧を使用している部分がありました。 例) { ←この括弧    my(@new);    for(0..3){if($tmp[$_]=~/jpg/){push(@new,$tmp[$_]);}} } 矢印の部分の部分の括弧ですが、これはどのような意味があるのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Perl
  • Perl UTF8 での氏名チェック

    ■環境 Linux, Perl 5.8 です。 画面(HTML)と処理(Perl)は分けて作成しており、Templateモジュールで画面表示を行っています。 HTMLもPerlも文字コードはUTF-8です。 ■質問 フォームからうけとった文字列で以下の文字以外をエラーとする入力チェック処理(正規表現)をUTF8用に作りたいです。 ・漢字 ・ひらがな ・全角記号(ー-のみ) ・全角スペース ・全角カタカナ(http://okwave.jp/qa4997637.html) 直前の全角カタカナチェック(http://okwave.jp/qa4997637.html)と類似しているのですが、別に質問させていただきました。 色々探してみたのですが、UTF8でそのようなチェックモジュールが見つからず、 正規表現で書くしかないのかと思い、正規表現でも書いてみましたがうまくいきませんでした。 チェックモジュールが存在するのであれば教えて頂きたいです。 または、以下のようなシンプルな書き方(以下はUTF8ではなくSJISの全角カタカナチェックですが)があればご教授頂きたいです。 また、文字コードの対応(例えば\x40が何の文字にあたるか)がUTF8で分かれば応用がきくのですが、 それも見つからなかったので、対応表、調べ方をご存知の方がいらっしゃったらご教授頂きたいです。 ・SJISの全角カタカナチェック if($data !~ /^(?:\x83[\x40-\x96])+$/){ $mes="全角カナ以外がありますよ"; } よろしくお願い致します。

  • Perl UTF8 での全角カタカナチェック

    ■環境 Linux, Perl 5.8 です。 画面(HTML)と処理(Perl)は分けて作成しており、Templateモジュールで画面表示を行っています。 HTMLもPerlも文字コードはUTF-8です。 ■質問 フォームからうけとった文字列で全角カタカナと特定の全角記号以外はエラーとする 入力チェック処理(正規表現)がうまくチェックを行ってくれません。 SJISだと以下のような書き方があるそうなのですが、UTF8での書き方がわかりません。 ・SJIS if($data !~ /^(?:\x83[\x40-\x96])+$/){ $mes="全角カナ以外の文字が指定されています"; } UTF8での書き方を教えて頂きたいです。 なお、許容する全角カタカナと特定の全角記号は以下のとおりです。 ========================================================== アイウエオカキクケコサシスセソタチツテトナニヌネノ ハヒフヘホマミムメモヤユヨラリルレロワヰヱヲン ァィゥェォッャュョヵヶヴガギグゲゴザジズゼゾダヂヅデド バビブベボパピプペポーヽヾ ========================================================== ご教授お願い致します。

  • Perlのバージョンに対応?非対応?CGIモジュール

    こんにちわ。 Perl初心者ですが、今度簡単なサーバー移行作業を お手伝いすることになり、ちょっとした疑問があります。 (単にCGIファイルやHTMLファイルを新サーバーにあげるだけ。) CGIモジュールというのを使ってプログラムをくんだ 場合、確かPerlのバージョンがモジュールに対応していないと動かなかったように思います。 ので、サーバー移行先で「CGIはパーミッションさえちゃんとしてくれれば動くから、CGIのチェックはしなくていい」といわれたので「CGIモジュールを使っている場合、Perlのバージョンが対応してないと動かないと思うんですけど大丈夫なんでしょうか?」と その仕事を提供してくれた人に聞いたところ 「PerlはOSに依存しないので問題ないです」とすっぱり言われました。 OSに依存しない?! ・・・意味がわかりません。 因みに移行先のサーバーのバージョンは 5.00503です。 これなら、どんなモジュールも対応しているのでしょうか?その担当の方にはもう聞きづらいかんじなので(私自身に知識がないこともあるので)教えていただきたいです。

    • ベストアンサー
    • Perl
  • perlを使ってファイル分割

    ーーーーーーーーーーーー SRR_1 X1 Y1 SRR_1 X2 Y2 ~ SRR_1 Xn Yn SRR_2 X1 Y1 SRR_2 X2 Y2 ~ SRR_3 X1 Y1 ~ SRR_xxx X1 Y1 ーーーーーーーーーーー このようなタブ区切りのファイルを、一列目のSRR以降の数字が変わるごとに以下のようにファイルを分割したいと思っています。 SRR_1.txt ーーーーーーー X1 Y1 X2 Y2 ~ Xn Yn ーーーーーーー SRR_2.txt ーーーーーーー X1 Y1 ~ Xn Yn ーーーーーーー perl初心者ですが、どうかよろしくお願いします。

    • ベストアンサー
    • Perl
  • perlでサブルーチンへの複数の配列渡し

    perlでサブルーチンに配列を渡しているのですが、 引数としている配列が1個の場合は問題ないのですが、 複数渡すと、第2引数以降が渡りません。 どの様にすれば上手くできますか。 例1 #!/usr/bin/perl @x1 = (14, 11, 5, 12, 8, 15); @x2 = (12, 10, 8, 9); print "main : @x1 \n"; &test(@x1); sub test { my (@arg1) = @_; print "sub : @arg1 \n"; } 結果 main : 14 11 5 12 8 15 sub : 14 11 5 12 8 15 例2 #!/usr/bin/perl @x1 = (14, 11, 5, 12, 8, 15); @x2 = (12, 10, 8, 9); print "main : @x1 \n"; print "main : @x2 \n"; &test(@x1, @x2); sub test { my (@arg1, @arg2) = @_; print "sub : @arg1 \n"; print "sub : @arg2 \n"; } 結果 main : 14 11 5 12 8 15 main : 12 10 8 9 sub : 14 11 5 12 8 15 12 10 8 9 sub : 引数1に全てが設定されて、引数2に設定されていない。

    • ベストアンサー
    • Perl
  • perl

    授業でperlをやっていて課題がでてるのですが、 よく分かりません。 200以上300未満の数字か否かを判断する物を作りたいです。 が、300以上だと反応はないのですが200未満でも反応があります。 どこが違うのか教えてください 2つあります。 (1) my $a= 118; if($a < 200 ){ print "" } elsif($a => 300 ){ print "" } else { print "OK.\n"; } (2) my $x =111; if ($x ge 200 && $x lt 300){ print "OK.\n"; }

  • Perlで配列の添え字を抽出したい

    Perl初心者で、既出の質問かもしれませんが、ご教授願います。 以下のように"*"が入っている値を抽出する処理があります。 ーーーーーー処理ーーーーーー @array = ('aaa', 'b*b', 'ccc', 'dd*'); foreach (@array) { if ($_ =~/\*/) { print "OK\n"; } else { print "NG\n"; } } ーーーーーーーーーーーーーーーー ーーー結果ーーー NG OK NG OK ーーーーーーーー <質問> 上記結果より、OKとなった値の配列(添え字)を取得するにはどのようにすれば宜しいでしょうか? 宜しくお願い致します。

    • ベストアンサー
    • Perl