m//gとm//gcにはどんな違いがあるのでしょうか。
いくつか解説を見たのですが、どれも「m//gではマッチに失敗すると通常は文字列の検索位置が文字列の先頭にリセットされるが、cをつける (m//gc) と、これを防ぐことができる」のような感じでさらっと説明されていて、イマイチ理解できません。スクリプトを適当に作成して試してみたのですが、cをつけてもつけなくても結果は変わらないような気がします。これは、つまり、cがあるときと無いときの違いは、効率の違いとして現れるだけで一般的にはcをつけておけばいいと考えていいのでしょうか。
http://perldoc.jp/docs/perl/5.6.1/perlop.pod#ite …
以下のスクリプトはindex関数的に配列@strの各要素文字列に含まれる検索文字列$findwordの位置を表示させるものですが、やはりcをつけてもつけなくても結果は変わりませんでした。
my @str = ('pattern match', 'at random', 'exponentiation operator');
my $findword = 'at';
my $len = length $findword;
print "search '$findword'\n\n";
foreach my $str (@str) {
my $count;
print '0123456789' x 3, "\n";
print "$str\n";
{
if ($str =~ /$findword/ogc) { printf("match%d: %d\n", ++$count, pos($str)-$len) }
else { print "\n"; last }
redo;
}
}
# /oはパターン内の不変変数を一度コンパイルすれば十分というものです
No.2
- 回答日時:
#以下を試してみたらわかりやすいかも
$text="bbb ddd 111 222 333";
print "option:g\n";
$text=~ /[a-z]+/g; print pos($text).":$&\n";
$text=~ /[a-z]+/g; print pos($text).":$&\n";
$text=~ /[a-z]+/g; print pos($text).":$&\n";#リセットされる
$text=~ /[a-z]+/g; print pos($text).":$&\n";
$text=~ /[a-z]+/g; print pos($text).":$&\n";
pos($text)=0; #reset
print "option:gc\n";
$text=~ /[a-z]+/gc; print pos($text).":$&\n";
$text=~ /[a-z]+/gc; print pos($text).":$&\n";
$text=~ /[a-z]+/gc; print pos($text).":$&\n";
$text=~ /[a-z]+/gc; print pos($text).":$&\n";
$text=~ /[a-z]+/gc; print pos($text).":$&\n";
回答していただき、ありがとうございます。
なるほど!このコード、とてもわかりやすいです。入門書などで下手にループとか使わずに、うまく説明されていたのを思い出しました。ループ処理には無関係で、マッチ変数にはこんな風に記憶されているんですね。
# すみません。ポイントの大小気にしないでください。とても感謝しています。
No.1ベストアンサー
- 回答日時:
gオプションにはパターンにマッチした部分を対象文字列から順次抜き出す機能があります。
@ary = $str =~ m/PATTERN/g;
とすると、$strからPATTERNにマッチする部分を全部抜き出し、配列に入れることができます。また、
$scl = $str =~ m/PATTERN/g;
とすると、マッチした文字列を一つずつ抜き出します。
$strがPATTERNにマッチすると1を返し、マッチした部分の次のインデックスをpos($str)関数で取得できます。
再度同じ文字列をm//gでマッチングするとき、pos($str)の位置から検索されます。
これ以上マッチする文字列が見つからない場合、pos($str)は先頭位置にリセットされます。
が、m//gcでは先頭位置にリセットされずに、一番最後にマッチしたインデックスがそのまま残ります。
以下のスクリプトを実行すると挙動が理解できると思います。
$s = 'hat hit hut het hot';
print "case m//g\n";
#マッチできなくなるまでループさせる
while(my $r = $s =~ m/(h.t)/g)
{
print pos($s)."\n";
}
#マッチできなくなったあとのposを取得
print 'lastpos' .pos($s)."\n";
print "case m//gc\n";
while(my $r = $s =~ m/(h.t)/gc)
{
print pos($s)."\n";
}
print 'lastpos' .pos($s) ."\n";
cオプションをつけただけで効率が変わることはないと思います。
kapuraさん添付のソースでは、各文字列に対し一度しかマッチングさせていないので、cはつけてもつけなくてもいいでしょう。
回答していただき、ありがとうございます。
直接の質問以外の点も説明していただいて、頭の整理ができました。示していただいたコードもわかりやすく、理解するのに役立ちました。
つまりcオプションをつけないつけるは、posで返される値をリセットするかしないかということで、もしループ処理の後で最後にマッチした位置を使う場合にはcオプションをつければいいと考えればいいのかな。
ということは、質問内で示したスクリプトは、else節を
else { printf("laspos: %d\n\n", pos($str)); last }
としたら違いが出るのかなと思って試したら、確かに結果が変わりました!
if節を囲む裸のブロックの部分は
while ($str =~ /$findword/og) { printf("match%d: %d\n", ++$count, pos($str)-$len) }
などと書いてもいいんですね。
# 理解が間違っていなければいいんですが・・このまま質問を締め切りたいと思います。このまま続けても感謝のポイントをさらに追加で渡すことができないので。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- PHP PostgreSQLからCSV形式でエクスポートする際にカラム内の改行をとる方法 1 2023/02/22 10:05
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
シェルスクリプトで、空白(ス...
-
pythonで演算子を変数に代入す...
-
Use of uninitialized value ---
-
Pythonでターミナルに文字を出...
-
UWSCのSELECT文の記述方法
-
16進の10進変換について
-
パイソンのクラスについて
-
【至急!!!】python言語で本を見...
-
数値英単語変換
-
javaのパッケージ構成で各パッ...
-
ポーリングとHTMLデータのリロ...
-
Tiny Basicのプログラムでもう...
-
数値かどうかの判定方法
-
Perl でワードファイルのヘッダ...
-
JSONで文字列が長い時
-
Application.ScreenUpdating = ...
-
CLispのloop内の挙動について
-
文字の横にプルダウンを表示さ...
-
formで特定のinputを送信しない...
-
どちのほうがすきですか?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
16進の10進変換について
-
Pythonでターミナルに文字を出...
-
シェルスクリプトで、空白(ス...
-
【至急!!!】python言語で本を見...
-
pythonで演算子を変数に代入す...
-
c言語 16進数の2進数への変換
-
パイソンのクラスについて
-
I2C接続のLCDディスプレイを使う
-
関数「exists」と「defined」の...
-
pythonの*
-
変数の中は文字列か数値か調べ...
-
数値かどうかの判定方法
-
python print文のエラー
-
int(input("○○"))の使い方
-
Perlの例文でif($a==1&&$b==5&&...
-
awkの正規表現での最左最短マッ...
-
Use of uninitialized value ---
-
CGIでimgタグでalignを使うとエ...
-
swift 文字コードから文字に変...
-
javaのパッケージ構成で各パッ...
おすすめ情報