Cで正規表現を使ってPerlの一部を実現する方法

このQ&Aのポイント
  • Cで正規表現を使ってPerlのような一部の処理を実現する方法について教えてください。
  • Perlでの正規表現パターン/^(.).*/gと同等の処理をCで行う方法を教えてください。
  • 具体的な例として、文字列$searchwordsに対して$ searchwords =~ /^(.).*/gが成立している間は、文字列の先頭の一文字を取り出す操作をどう実現すればよいか教えてください。
回答を見る
  • ベストアンサー

perlの正規表現をCで・・

while($searchwords =~ /^(.).*/g) たとえばperlでこのような文があったとします。 Cでならwhile文おそらくperlでも同じと思いますが 条件が真の時にぐるぐる回ります。 この場合の条件が おそらく一文字目以降を切り取るということだと思います。 $searchwords =~ /^(.).*/gが成立している間?whileするということなのでしょうか? もし$searchwordsに12345678が入っているとすると 一文字ずつ横にずれていくと言うことでしょうか? perlで質問するべきだと思いましたが・・。 Cで書きたいのでどうしたらよいのかと質問しました。 $a =~ s/^(.)//; ならば 行の先頭文字を一個消してaに入れているということになるから char a[] = "123456789"; ならばa[9]になります。 だからa[0] = a[1]ってな感じで一個ずつずらせばいいんだと勝手に思っていますが while($searchwords =~ /^(.).*/g) の場合Cではどのように記述したら良いのでしょうか?あとこの式の意味もわかりやすく教えてください。 こんがらがってしまっている面が強いかもしれません。

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

  • ベストアンサー
回答No.2

そういうことですか。それならばループしますね。1文字づつ $1 に入ります。(元の文字列が 'ab' だったら1回目に 'a' が $1 に入り、2回目に 'b' が $1 に入ります)。 ただ、そうならばこう書いても $1 に入る文字は一緒です。 while($searchwords =~ /(.)/g) {  # ここで print "$1\n"; などとすると  # 1文字づつ取り出される様子が分かる。 } Cでやるとするとこんな感じになります。 char a[] = "abcdefg"; /* 元の文字列 */ char c; /* 取り出した1文字を入れる変数 */ int i; /* 取り出す位置を決める変数 */ for (i = 0; a[i]; i++) {  c = a[i];  /* ここで putchar(c); などとすると1文字出力される。 */ } for の終了条件が a[i] だけでもちゃんと動く理由は、Cはこのような宣言でダブルクォーテーションで括った文字列で初期化すると文字列の終りに必ず '\0' が入るためです。

mudai_yeh
質問者

お礼

それとわからないのがもうひとつあります。 my ($a, $b, @c, $d, %e, $f_g); とか push(@ulist, search_google($search_host, $1, 0, 100)); if($#ulist != $arrsize) { $arrsize = $#ulist; push(@ulist, search_google($search_host, $1, 100, 100)); } とかです。 いろいろなサイトから抜粋しているのでごちゃごちゃですいません。 これらの意味も説明していただけないでしょうか?できればCでの書き方もよろしくお願いします。そのほうがわかりやすかったりもします。

mudai_yeh
質問者

補足

for (i = 0; a[i]; i++) {  c = a[i];  /* ここで putchar(c); などとすると1文字出力される。 */ } これがa[7]のときループは終わるのでしょうか? あと while($searchwords =~ /^(.).*/g) { $searchwords =~ s/^(.)//;    //何らかの処理 } は for (i = 0; a[i]; i++) {  c = a[i];  /* ここで putchar(c); などとすると1文字出力される。 */ }と同じということは a[i]が成立していることが条件なので a[i]が\0などを参照するとループを出るということなのでしょうか?

その他の回答 (1)

回答No.1

まずその正規表現ですが、一番最初に ^ 記号があるため、g オプションの意味が全くなくなっています(もし ^ がなかったとしても最後に .* があるためこの場合やはり意味がありません)。で、結局 $1 に $searchwords 先頭の1文字が入って一回でループを抜けます。つまり while で書く必要性がありません。単に $searchwords =~ /^(.)/; と書いた時と全く同じ結果になります。 Cで書くとしたら、たとえば char a[] = "abcdefg"; と初期化されていたならば a[1] = '\0'; とやって a を結果とするか、または別に char b[2]; などと配列を作っておいて b[0] = a[0]; b[1] = '\0'; とやって b を結果とすればできます。(どちらかというと後者の方がPerlのやっていることに近いです。Perl のパターンマッチは元の文字列を壊しませんから)。

mudai_yeh
質問者

補足

実際に動いているプログラムを使ったことがあります。 おそらく一回で抜けることはないと思いますが。。。 もしかしたらwhileのループ内でサーチワードをずらしているのかも知れません。 >whileで書く必要はありません。 実際わたしがwin32コンソールに移植しようとしているperlソースはwhileを使ってあります。 cygwinで使用したこともあり、1回でループは抜けないと思います。。 while($searchwords =~ /^(.).*/g) { $searchwords =~ s/^(.)//; } ソースから抜粋しましたが。。実際のソースはこうなっているから動作するのでしょうか?

関連するQ&A

  • Perl・正規表現が分かりません

    Perlでプログラムを書く場合、 ある文字列の文字数が5文字且つ、文字列の先頭に[0-5A]を必ず含み、そして残り4文字にも[0-5A]のみを必ず含む場合、Trueを表示。 それ以外はErrを表示する。 多分、全て、正規表現でできると思うのですが、分かりません。教えていただけないでしょうか? 宜しくお願い致します。 $test = "0AAAA"; if(正規表現){ print "True"; }else{ print "Err"; } ↑結果:True $test = "aAAAA";の場合、 結果:Err

    • ベストアンサー
    • Perl
  • 複数のperlの正規表現をひとつにまとめるには。

    こんにちわ。perlの正規表現について教えてください。 unless ($a =~ /[0-9]/){ &err1('数字をいれてください'); } unless ($b =~ /[0-9]/){ &err1('数字をいれてください''); } unless ($c =~ /[0-9]/){ &err1('数字をいれてください''); 上の3つのunless文は$a,$b,$c以外はすべて同じなのでこれをひとつにしたいのですが、どうやって記述すべきでしょうか?($a,$b,$c=~ /[0-9]/)とか($a =~ /[0-9]/ or $b =~ /[0-9]/ or $c =~ /[0-9]/)ってやってみてもだめでした^^教えてください。

    • ベストアンサー
    • CGI
  • C言語について

    C言語でif文の条件指定の際、a > b && c > dとe > f && g > hのどちらかが成立すれば真という条件を書きたい場合、a > b && c > d || e > f && g > hという文では間違いですよね? どのように表記すればいいでしょうか? 解答よろしくお願いします。

  • 【Ruby or Perl・正規表現】ある文字列の先頭5文字を残して削除するには?

    初心者質問で恐縮です。 RubyもしくはPerlで、ある文字列の先頭5文字を除く文字をすべて削除する(先頭5文字のみの文字列にする)には、どのような記述をすればよいでしょうか。 教えていただけるとうれしいです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • Perlで使える正規表現を教えて下さい。

    Perlで使える正規表現を教えて下さい。 半角英語で、小文字が3文字以上続いた後、大文字が来る場合、その大文字の右にスペースを入れる。 これをPerlで使える正規表現を教えて頂けないでしょうか? 例 $str = 'AaaAaaaBbbbbCccccDddBbA'; # Aaa Aaaa Bbbbb Ccccc DddBbA ちなみに、色々ネットで調べて試してみて、 $str =~ s/([a-z])([A-Z])/$1 $2/g; が最も近いコードになったのですが、2文字続いただけでもスペースが入り困っています。 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 正規表現について

    正規表現につての質問です。 今テキストファイルに下記のような漢字と数字が並んでいます。 そこから、漢字一文字だけの行を抜き出してきたいのですが、うまくいきません。PerlとCygwinを使用しています。よろしくお願いします。 人584504122 情報542701982 商品510342870 日414551872 方347990908 者347069359 中339925319 表示330177395 的324961911 私323727263 検索291502623 見ル285226619 場合275698771 一256241900 利用253752129 年240881734 時239273060 前228762989 店225241510 登録224560617   ・   ・    ・ プログラム中身 #! /usr/bin/perl -w #テキストから指定した単語などとマッチすると、 #その単語を含んだ文を抜き出してくる。 while(<>){ s/ +//g; s/\s+//g; if(/^([亜-煕]|[一-龠]){1}[0-9]*/){ print; print "\n"; } }

  • 正規表現を教えてください。

    SPAMの自動削除をするツールを使っています。 RE:という3文字だけのタイトルのメールがきたら削除させたいのですが、私の使っているツールはRE:という文字を指定するとRE:が先頭に付いているタイトルのメールを全て削除してしまいます。 つまり指定した文字を含むという条件だけが指定可能で、指定した文字と長さも一致という条件は指定できません。 ただ、このツールは正規表現も使用できるようです。 そこで、RE:という3文字だけの時は真となり、RE:の後ろに文字が付いているときには偽となる正規表現を教えてください。

  • 正規表現中の()について

    正規表現中の()について 繰り返し正規表現を行い、マッチ部分を配列に入れる場合の疑問です。 今回、while文を使わずに書いてみようとしています。 #3個以上数字が連続していたら、配列へ入れる。…(1) my @data = ( $str =~ /\d{3,}/g ); #3個以上連続している、同じ文字を取り出して、配列へ入れる。…(2) my @data = ( $str =~ /(.)\1{2,}/g ); 1つめのほうは期待通りに動きました。 が、2つめは正規表現内の()で囲まれた範囲しか、配列に入ってくれませんでした…。 具体的には、$str='AAABBB'なら、 @data='A','B'になってしまいました。(AAA,BBBを配列に入れたい) たぶん、while文と$&を使えば書けそうだとは思いますが、 今回は、この書式で期待通りに動かす方法を知りたいです。 AAA,BBBを配列に入れるにはどのように書けばよいでしょうか? どうか、ご教授ください。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • 正規表現についての質問です。

    正規表現につての質問です。 今テキストファイルに下記のような漢字と数字が並んでいます。 そこから、漢字一文字だけの行を抜き出してきたいのですが、うまくいきません。PerlとCygwinを使用しています。よろしくお願いします。 人584504122 情報542701982 商品510342870 日414551872 方347990908 者347069359 中339925319 表示330177395 的324961911 私323727263 検索291502623 見ル285226619 場合275698771 一256241900 利用253752129 年240881734 時239273060 前228762989 店225241510 登録224560617   ・   ・    ・ プログラム中身 #! /usr/bin/perl -w #テキストから指定した単語などとマッチすると、 #その単語を含んだ文を抜き出してくる。 while(<>){ s/ +//g; s/\s+//g; if(/^([亜-煕]|[一-龠]){1}[0-9]*/){ print; print "\n"; } }

  • perlの正規表現 (ワンライナー)

    以下のような文字列から2つの要素だけ抽出するようなperl/rubyのスクリプトはどのように書いたらいいでしょうか? できればワンライナーで実現したいです(が、ワンライナーとしてはちょっと複雑なのでしょうか。。。) 元の文字列 -test t001 +opt0=1024 -N n_paramX -seed 1 -test t002 +opt0=1024 -opt1=2486 -N n_paramY -test t003 +opt3=1234 -N n_paramZ ... 整形後の文字列 t001 n_paramX t002 n_paramY t003 n_praramZ ※ 各行に -test と -N が必ず存在していることは仮定してOKです スクリプトで記述した場合: while(<>) { /\-test (\S+)/; $match00 = $1; /\-N (\S+)/; $match01 = $1; print "$match00 $match01\n"; } よろしくお願いします