こういう場合は「否定先読み」の正規表現を使った方がすっきりするな

あるディレクトリに、

・頭4桁が月日(色々な月日のファイルが混在)
・その後に1文字のアルファベット(まあ、他の文字でもいいんだけど)
・その更に後ろに2桁の数字
・最後に、JPEG の拡張子(.jpg)

という命名条件のファイルがあった時、そのファイル一覧の中から、2月9日(0209)の日付のもので、

(1)アルファベットの後ろの 2桁の数字が 01 のものをまず抽出したい。
(2)その後、2桁の数字が 01以外のファイルを抽出したい。

という時、(1) のファイル名に当てる正規表現は簡単だよな。

例えばファイル名の一覧が、

0209C01.jpg
0209C02.jpg
0209Q38.jpg
0209C10.jpg
0209A28.jpg
0210C28.jpg
0209Y28.jpg
0212C01.jpg

だったら、

if ($d =~ /^0209.{1}01\.jpg$/) {...}

で 0209C01.jpg だけがマッチする。(.{1}のところは、[A-Z]{1}じゃないかと言われそうだけど、ここには必ずアルファベットが入っているので .{1}で十分なんだ。{1}はいらないけど、わかりやすくするためにね)

じゃあ、(2) の抽出はその否定でいいのか?って言うと、それは駄目だよね。

if ($d !~ /^0209.{1}01\.jpg$/) {...}

では、

0209C02.jpg
0209Q38.jpg
0209C10.jpg
0209A28.jpg
0210C28.jpg
0209Y28.jpg
0212C01.jpg

が全部マッチしてしまう。実際にマッチさせたいのは先頭が 0209 のものだけなのに。

まあ、

if ($d !~ /^0209.{1}01\.jpg$/ && $d =~ /^0209/) {...}

とすればいいんだけど、何か 2つの条件を && でつなげるのも格好悪いなあ、何となく。

こういう時に、日頃はあんまり使わない「否定先読み」を使うと正規表現一発で済むので格好良い。

if ($d =~ /^0209.{1}((?!01).){2}\.jpg$/) {...}

これなら、

・2月9日(頭 4桁が 0209)のものだけで
・アルファベットの後ろの 2桁が 01 以外のもの

にマッチするので、上記の例なら、

0209C02.jpg
0209Q38.jpg
0209C10.jpg
0209A28.jpg
0209Y28.jpg

がマッチして幸せなのである。

トラックバック(0)

このブログ記事を参照しているブログ一覧: こういう場合は「否定先読み」の正規表現を使った方がすっきりするな

このブログ記事に対するトラックバックURL: https://blog.netandfield.com/mt/mt-tb.cgi/2165

コメントする

このブログ記事について

このページは、shinodaが2012年8月18日 01:54に書いたブログ記事です。

ひとつ前のブログ記事は「なんとか雨も降らず、別所畑地区の盆踊りも終了したのであった」です。

次のブログ記事は「次男坊はもう少年野球チームを辞めたのだが(^^;」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら