• ベストアンサー

perlで記号除去を行いたいのですがうまく行かない

perlで記号除去を行いたいのですがうまく行かず困っています。 文字列はEUCです。そこから$patternのような記号を削除したいのですが・・・。 http://www.din.or.jp/~ohzaki/perl.htm#Character 正しくパターンマッチさせる を参考に $ascii = '[\x00-\x7F]'; $twoBytes = '[\x8E\xA1-\xFE][\xA1-\xFE]'; $threeBytes = '\x8F[\xA1-\xFE][\xA1-\xFE]'; $pattern=q([\!!\##\%%\--―ーー・・\//\;;\??\\¥__`‘\{{\}}\++\((\))\[[\] ]\**@@\$$&&\::\>>\<<\~ ̄\^^\"”\'’  \,,\..\==\||\、、\。。]); if ($data =~ s/((?:$ascii|$twoBytes|$threeBytes)*?)(?:$pattern)/$1/mg) { print "マッチした $& \n"; } print $data; として$dataに下の2つを与えてみました。 サンプル1 【あいうえお】 サンプル2 【aaa】 ところが・・・ サンプル1 (出力なし) サンプル2 旻aaa桿 何が悪いのかわかりません・・・ ためしにパターンに【】を追加したところサンプル2はうまく行きましたが サンプル1に変化がありません。(あいうえお も消えてしまう) 何か思い当たる点がありましたら教えてください。よろしくお願いいたします。

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

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

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.3

正規表現の[~] の中で全角文字を使っているのが原因でしょう。 たとえば、%はEUCで \xa1\xf3 ですから、[%%] は、「\x25 か \xa1 か \xf3」という1バイトにマッチします。 そういう場合は、 正規表現を [\!\#\%\-…]|!|%|-|… といった感じで、 全角文字は | で並べる形にするのがいいでしょう。 あるいは、一手間かかりますが、エンコーディングの処理をして、 スクリプトはuse utf8しておけば、 $ascii|$twoBytes|$threeByte みたいな文字の境目チェックは不要で、 $data =~ /[!#%]/ と書くだけでも全角文字にマッチさせられます。

azicyan
質問者

補足

おおおおお!!!! うまくいきました!! ただ、性能はものすごく悪いみたいです(泣 やはり泣き別れ防止の ?:$ascii|$twoBytes|$threeBytes のあたりがよくないみたいですね。 あまり文字列が長いとコアダンプするし・・・ # ただし、最近のlinuxではコアダンプしないみたいです。 でも できてすっきりしました! ありがとうございました!!

その他の回答 (2)

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

もちろん Perl でもできます>#1. というか, その方が普通.

  • A88No8
  • ベストアンサー率52% (834/1602)
回答No.1

こんにちは  たぶん、UNIX系の環境ですよね。  なかなかメッセージが付かないようなのでにぎやかしということで(^^;  難しく考えないで $pattern の文字があったら繰返し削除じゃだめですか?  例えば、sed だったら 「s/$pattern//g」という雰囲気 (sedですから、当然 $pattern は展開して記述しますけど)。  perl でも同様にできないでしょうかね。 コードを眺めたらできそうな気がしましたので。  それと\でエスケープするメタ文字ってそんなに多かったですか? /*+.,?$\[]^{}|() ←16文字よりありましたっけ?  外してたら、ごめんなさい。

azicyan
質問者

補足

回答ありがとうございます。 展開して書くということは、 1文字ずつ書くということでしょうか?

関連するQ&A

  • perlで正常に検索できない

    CGI RESCUE さんの 簡易データベースでdatファイルを検索しようとしています。。 http://www.rescue.ne.jp/cgi/database/ キーワードで検索をしようとしているのですが、うまくヒットしません。 CGIは以下のようになっています。 # キーワード(フリーワード)  if ($FORM{'keyword'} ne '') {   if ($com5 =~ /^([\x00-\x7F]|[\x8E\xA1-\xFE][\xA1-\xFE]|\x8F[\xA1-\xFE]{2})*$FORM{'keyword'}/i) { ; }   elsif ($com4 =~ /^([\x00-\x7F]|[\x8E\xA1-\xFE][\xA1-\xFE]|\x8F[\xA1-\xFE]{2})*$FORM{'keyword'}/i) { ; }   else { next; } } $com5には「スズキ用<br>ドアトリム<br>バックミラー」と入っていたとします。 「スズキ」または「ドア」・「ドアトリム」・「トリム」と入力すると、ヒットします。 「バック」または「バックミラー」で検索するとヒットしません。 改行が悪いのかと思い、 $com5を「スズキ用ドアトリムバックミラー」に修正してみました。 同じように「スズキ」等はヒットするのですが、「バック」または「バックミラー」で検索するとヒットしません。 「バックミラー」と言う語句がヒットしないのかと思ったのですが・・・ $com5を「バックミラードアトリムスズキ用」に修正したとします。 「バック」・「バックミラー」でヒットします。 また、「ドア」・「トリム」まではヒットしますが、「スズキ」・「スズキ用」になるとヒットしなくなります。 全くヒットしなかったり、動作しないわけではないので、そもそもが間違っているとかではなく検索する部分で何か文字数制限があるような感じですが、これはどこを修正したら良いでしょうか? 他に情報を記入しないといけない物があれば指摘お願いします。

  • パターンマッチングの限界?(最大文字数)

    perl正規表現のパターンマッチングでは,対象文字列が長すぎると正しくマッチしないというような,perlの仕様あるいはバグが存在するのでしょうか? ■状況 CGIフォームから入力された文字列に機種依存文字(EUC未定義文字)が含まれていないかチェックするため,以下のようなスクリプトを書きました。テストでは,ほとんどの場合は正常に動作しましたが,定義文字=パターンマッチするはずの文字に,未定義文字が含まれていると誤判断されてしまうケースがありました。いろいろ試してみたところ,どうも文字数32,768バイトを超えた場合に限られるようだ,というところまで判りました。 ドキュメントなどを見ても,そのような仕様については見つからず,どなたかご存知ないでしょうか。 あるいはスクリプトに不備があればご指摘いただけたらと思います。 よろしくお願いいたします。 if (&is_undef($input_text)) { print "未定義文字が含まれています。"; } … sub is_undef { my ($text, $character_strict); $text = $_[0]; # EUC-JP文字(定義文字) $character_strict = '(?:[\x20-\x7E]|' # ASCII  . '[\xA1\xB0-\xCE\xD0-\xF3][\xA1-\xFE]|' # 1,16-46,48-83区  . '\xA2[\xA1-\xAE\xBA-\xC1\xCA-\xD0\xDC-\xEA\xF2-\xF9\xFE]|' # 2区  . '\xA3[\xB0-\xB9\xC1-\xDA\xE1-\xFA]|' # 3区  . '\xA4[\xA1-\xF3]|' # 4区  . '\xA5[\xA1-\xF6]|' # 5区  . '\xA6[\xA1-\xB8\xC1-\xD8]|' # 6区  . '\xA7[\xA1-\xC1\xD1-\xF1]|' # 7区  . '\xA8[\xA1-\xC0]|' # 8区  . '\xCF[\xA1-\xD3]|' # 47区  . '\xF4[\xA1-\xA6])'; # 84区 $text =~ s/\r//g; $text =~ s/\n//g; $text =~ s/\t//g; if ($text =~ /^$character_strict*$/) {  return; } else {  return 1; } }

    • ベストアンサー
    • Perl
  • perl マッチさせる方法について

    perlでマッチさせたいのですが、なかなかうまくいきません。。 詳細は $joho='これは、テストです。'; $seach='テスト'; if ($joho =~ m/$seach/) { print 'マッチしました。'; } とやっていますが、どうしてもだめです。 if ($joho =~ m/テスト/) { print 'マッチしました。'; } とすれば、マッチするのですが、何がいけないのでしょうか? 環境はperl5.8、EUC-JPです。 初心者な質問かもしれませんが、よろしくお願いします。

  • 半角と全角の文字数カウント方法

    半角の一文字を1とカウントし、全角の一文字も1とカウントしたいのですが、うまい方法を教えてください。 例) 1111ああああ → 8文字 11111111 → 8文字 ああああああああ → 8文字 自分なりに調べて見たら以下の命令を見つけたのですが、うまく行かないのです。 $n =~ tr/\x00-\x7f/\x00-\x7f/; $nn =~ tr/\xa1-\xfe/\xa1-\xfe/; 宜しくお願いします。

    • ベストアンサー
    • Perl
  • perl でこのマッチは失敗しますか?

    perl でこのマッチは失敗しますか? my $one = "FEFRGrgarGEEeg+05fweaEFJIEI+A"; my $str = "FEFRGrgarGEEeg+05fweaEFJIEI+A"; if($str =~ m/$one/){ print "same"; }else{ print "difference"; } exit; 5時間ほど悩んでそれらしいところを見つけたのですが、この部分で失敗しているようでした。 「+」記号がある為だと思うのですが、何故、このようなことになるのでしょうか? このように、失敗するような避けるべき文字ありますか? また、+記号などがあっても正しくマッチを使う方法はありますでしょうか?

    • ベストアンサー
    • Perl
  • 3バイト文字を書きだしたい

    恐れ入ります。 表題の通りなのですが、うまく出来ません>< 3バイト文字の判定が \x8F[\xA1-\xFE][\xA1-\xFE] ということでしたので、 試しに以下のようにしてみたのですが、ダメでした。 for ( 161 .. 254 ){ my $tmp=sprintf("\x8f\xa1\x%x", $_); print $tmp; } 【結果】 a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe

    • ベストアンサー
    • Perl
  • perlでWin32::APIを使用してDLLからバイナリデータを得たいのですが、

    perlでWin32::APIを使用してDLLからバイナリデータを得たいのですが、 データ途中できれてしまいます。 0x00を含むところで切れているように思えます。 $datの長さを指定する方法とかあるのでしょうか? どうか助言をお願いします。 $func=new Win32::API("sample.dll","func1",[P,N,P],P); $size=0; $dat = $func ->Call("TEST",100,\$size); open(F,">kekka"); binmode(F); print F "$dat"; close(F);

    • ベストアンサー
    • Perl
  • Perlのデータ構造について

    Perlのデータ構造でわからないところがあります。 ハッシュの配列で、以下の構造がある場合 my %hash_array = ( 1=>["aaa", "bbb"], 2=>["ccc", "ddd", "eee"], 3=>[], 4=>["fff"] ); print $hash_array{1}[0]; # aaaが表示される。 print $hash_array{2}[2]; # eeeが表示される。 ですが、 $hash_array{1}は 2 $hash_array{2}は 3 $hash_array{3}は 0 $hash_array{4}は 1 のように個数を表示させるのは、どうすればよいでしょうか? Perlのデータ構造に詳しいサイトや書籍はありますか? また、Perl 5.6.1から Perl 5.8.7に乗りかえようとしていますが、 データ構造など大幅に変わった点はあるのでしょうか?

    • ベストアンサー
    • Perl
  • PerlでJavaScriptを作成しているのですが・・・

    PerlでJavaScriptを作成しているのですが、以下の部分で困っています。 たとえば、Perlの変数「$codes」に「AAA\nBBB\nCCC\n」が入っているとします。 ----------------------------------------------------------------------  print <<"END_OF_HTML";  function sample()  {   document.FORM.ele.value="$codes";  }  END_OF_HTML ---------------------------------------------------------------------- とPerlで記述すると、作成されたソースは、 ----------------------------------------------------------------------  function sample()  {   document.FORM.ele.value="AAA  BBB  CCC  ";  } ---------------------------------------------------------------------- となり、JavaScriptエラーになってしまいます。 Perlでエンコードしてから、JavaScriptでデコードしてみよう!と試してみたのですが、Perl⇔JavaScriptのエンコード/デコードがうまくいきませんでした。 (Perlでエンコードした値が、JavaScriptで元の形に戻せませんでした。わたしの能力不足です。。。) どなたか、よい方法をご存知ないでしょうか?よろしくお願いします。

    • ベストアンサー
    • Perl
  • perlを使ったファイルの入出力について

    perl 初心者です。 perl を使ってデータ整理を試みていますが、方法がわからなくて困っています。 やりたい操作は、 1、ディレクトリ内にある特定の拡張子をもつすべてのデータファイルを読み込む 2、データソート 3、データファイル名を変更せずに、ソートしたデータを出力する 例 ディレクトリに以下のデータファイルがあるとします aaa.data bbb.data ccc.data : zzz.data これらのデータファイルをすべて読み込み、中身を整理した後に aaa.txt bbb.txt ccc.txt : zzz.txt となるように、それぞれのデータの名前を変更せずに出力したいと思っています。 スクリプトのサンプルなんかがあればありがたいです。

    • ベストアンサー
    • Perl

専門家に質問してみよう