アプリ版:「スタンプのみでお礼する」機能のリリースについて

# 正規表現 最長マッチが、機能しない。
#
# Windows XP(sp3) ActivePerl
#
# This is perl 5, version 12, subversion 3 (v5.12.3) built for MSWin32-x86-multi-thread
# (with 9 registered patches, see perl -V for more detail)
#
# Copyright 1987-2010, Larry Wall
#
# Binary build 1204 [294330] provided by ActiveState http://www.ActiveState.com
# Built Feb 9 2011 14:38:22
#
use strict;
use utf8;
use Encode;
my $doc = "(L)12×(H)34×(W)56\n";
$doc =~ s%(\([LHW]\)(\d+))([^×cm])%$1cm$3%ig; # ←この部分
print encode("cp932", $doc);

{出力結果}
(L)1cm2×(H)3cm4×(W)56cm

A 回答 (8件)

条件が細かく変わり続けているので自信ありませんが・・・


推測込みでまとめるとこういうかんじでしょうか

1,
(L)12×
の「ようなもの」が続くとき、末尾の一つには×がつかない

2,
末尾ひとつの「ようなもの」の直後に、「cm」がなかった場合だけ「cm」を付与したい

http://ideone.com/7hrZH
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
これで、解決しました。

お礼日時:2011/10/29 23:12

use strict;


use warnings;
use utf8;
use v5.12;

while (<DATA>) {
s/\([LHW]\)\d+\K$/ cm/m;
print;
}
__END__
(L)12×(H)34×(W)56
(L)12×(H)34
(L)12
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
正規表現の¥Kの意味が、わかりません。
実は、¥nのととろは、どんな文字が、来るかわからないのです。
要するに、cmが、なければ、cmを、挿入したいのです。

お礼日時:2011/10/28 22:11

「入力の\nの前に、cm が、ない場合にのみ、cm を、つけたい」なら


s/(?<!cm)\n/cm$&/;
のような感じでいいんじゃないかな. あるいは \n のかわりに $ を使うともっと簡単かも.
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
実は、¥nのととろは、どんな文字が、来るかわからないのです。
要するに、cmが、なければ、cmを、挿入したいのです。

お礼日時:2011/10/28 22:02

となると、多分意図されているのはこの辺でしょうか


改行直前に、こういったパターンがあった場合だけcmをつけるという・・・

http://ideone.com/8Kf91
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
実は、¥nのところに、cmが、なければ、cmを、挿入したいのです。
¥nも¥n以外の文字であるかもしれません。

お礼日時:2011/10/28 21:57

量指定子でマッチした次の正規表現でマッチしないと、一個づつ戻ってマッチできるか確認します。


正規表現エンジンの側に立って考えるとよくわかります。
以下、表示がずれるので空白2文字を全角空白にしていることに注意。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Encode;

# 正規表現デバッグ
use re 'debug';

# 話を簡単にするために、全角Xを英字のxにする、g と i 演算子を外す。()も外す
my $doc = "(L)12x(H)34x(W)56\n";
$doc =~ s/\([LHW]\)\d+[^xcm]/AAA/;
print encode("utf8", $doc);

__END__
$ perl -w foo.pl

# 正規表現 "\([LHW]\)\d+[^xcm]" がコンパイルされると以下のようになる。
Compiling REx "\([LHW]\)\d+[^xcm]"
Final program:
  1: EXACT <(> (3)
  3: ANYOF[HLW][] (14)
 14: EXACT <)> (16)
 16: PLUS (18)
 17:  DIGIT (0)
 18: ANYOF[\0-bd-ln-wy-\377][{unicode_all}] (29)
 29: END (0)
anchored "(" at 0 (checking anchored) minlen 5
Guessing start of match in sv for REx "\([LHW]\)\d+[^xcm]" against "(L)12x(H)34x(W)56%n"
Found anchored substr "(" at offset 0...
Guessed: match at offset 0

# 正規表現 "\([LHW]\)\d+[^xcm]" で 文字列 "(L)12x(H)34x(W)56%n" を解析
Matching REx "\([LHW]\)\d+[^xcm]" against "(L)12x(H)34x(W)56%n"
  0 <> <(L)12x(H)3>     | 1:EXACT <(>(3) # ( にマッッチした
  1 <(> <L)12x(H)34>    | 3:ANYOF[HLW][](14) # L にマッチした
  2 <(L> <)12x(H)34x>    | 14:EXACT <)>(16) # ) にマッチした
  3 <(L)> <12x(H)34x(>   | 16:PLUS(18) # 数字 2 文字にマッチした
                 DIGIT can match 2 times out of 2147483647...
  5 <(L)12> <x(H)34x(W)>  | 18: ANYOF[\0-bd-ln-wy-\377][{unicode_all}](29)
                  failed... # [^xcm]にマッチしなかった
  4 <(L)1> <2x(H)34x(W>   | 18: ANYOF[\0-bd-ln-wy-\377][{unicode_all}](29) # 1文字戻したらマッチした
  5 <(L)12> <x(H)34x(W)>  | 29: END(0)
Match successful!
AAAx(H)34x(W)56
Freeing REx: "\([LHW]\)\d+[^xcm]"
    • good
    • 0
この回答へのお礼

詳しい解説、ありがとうございます。
正規表現デバッグは、よくわかりませんが、マッチさせるために、1文字戻すと、いうことですね。

お礼日時:2011/10/28 21:52

(\d+) が (12), (34), (56) にマッチすると、つぎの文字は×なので ([^×cm]) に一致しません。



なので、(\([LHW]\)(\d+))([^×cm]) に一致するのは先頭だと (L)12 になり、これが最長一致になります。

(\([LHW]\)(\d+))([^×cm]) の部分を (\([LHW]\)(\d+))(×|) にすれば期待するものになるのではないでしょうか。
    • good
    • 0
この回答へのお礼

ご回答、ありがとうございます。

私が、期待した、結果は、(L)12×(H)34×(W)56cm\n です。
また、入力が、(L)12×(H)34\n なら、(L)12×(H)34cm\n に、
(L)12\n なら、(L)12cm\n に、なって、ほしいのです。(数字の部分の桁数は、可変です。)
入力の\nの前に、cm が、ない場合にのみ、cm を、つけたいのです。
もし、お分かりになれば、期待する結果になる正規表現を、教えてください。

お礼日時:2011/10/26 23:24

1,


12
に対して、
\d+

マッチします

2,
但し、次に来る
×

[^×cm]
がマッチしないため、\d+ = 12 というケースは除外されます。

3,
1
に対して、
\d+

マッチします

4,
次に来る
2

[^×cm]
もマッチします。
ということで、こちらが採用(?)されます。

・・・というような、動作に至るイメージの事でいいでしょうか?
あんまし正確では無いかもしれませんが、何で\d+が12にならないのかは表現できたかなと

最後の56に関しては、×ではなく\nなので、[^×cm]へマッチしますよね?
試しに\nを外してみてください
    • good
    • 0
この回答へのお礼

Perlは、できるだけ、マッチさせようと、するのですね。
勉強になりました。ありがとうございます。

私が、期待した、結果は、(L)12×(H)34×(W)56cm\n です。
また、入力が、(L)12×(H)34\n なら、(L)12×(H)34cm\n に、
(L)12\n なら、(L)12cm\n に、なって、ほしいのです。(数字の部分の桁数は、可変です。)
もし、お分かりになれば、期待する結果になる正規表現を、教えてください。

お礼日時:2011/10/26 23:13

最長マッチ自体は動いていると思いますよ


http://ideone.com/LLDQ0

桁区切りのとこまでしかマッチしないのは、次の部分じゃないでしょうか
[^×cm]

×cmという三文字1セットの否定ではなく、(×|c|m)の否定になっています。
2,4,6はこの何れにもマッチしないため、そこで区切られるという・・・
    • good
    • 0
この回答へのお礼

>×cmという三文字1セットの否定ではなく、(×|c|m)の否定になっています。
はい、それは、わかっています。

(\d+) が、(12), (34), (56) に、マッチするはずです。
なぜか、(1), (3), (56) に、マッチしているため、cm が、それぞれに、挿入されています。
(56) だけは、正しいですけど。

お礼日時:2011/10/26 21:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!