<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>へびにっき &#187; 正規表現</title>
	<atom:link href="http://wp.serpere.info/archives/tag/%e6%ad%a3%e8%a6%8f%e8%a1%a8%e7%8f%be/feed" rel="self" type="application/rss+xml" />
	<link>http://wp.serpere.info</link>
	<description>樹上で暮らすヘビのように生きたい</description>
	<lastBuildDate>Mon, 06 Sep 2010 07:43:34 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>「末尾がxyzで終わってはいけない」正規表現</title>
		<link>http://wp.serpere.info/archives/477</link>
		<comments>http://wp.serpere.info/archives/477#comments</comments>
		<pubDate>Fri, 15 May 2009 08:41:06 +0000</pubDate>
		<dc:creator>tkyk</dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[正規表現]]></category>

		<guid isPermaLink="false">http://wp.serpere.info/?p=477</guid>
		<description><![CDATA[とあるソフトウェア製品での出来事。 あるバグフィックス・アップデートを適用して以来、それまでは問題なかった入力値でValidation Errorが出るようになった。丸一日調べ回った結果、以前は ^[a-z0-9_\-][a-z0-9_\.\-]*$ だった入力チェックの正規表現が、 ^[a-z0-9_\-][a-z0-9_\.\-]*[^x][^y][^z]$ に変わったため、と判明した（xyzは架空）。どうやら「末尾がxyzで終わってはいけない」という条件を追加したかったようだが、この正規表現は完全に誤りだといえる。これだと最低でも4文字以上ないとマッチしないし、&#8217;boxes&#8217;のような正当なはずの文字列にもマッチしないし、逆に&#8217;a+:^&#8217;のような不正であるべき文字列にマッチしてしまう。 では「末尾がxyzで終わってはいけない」を表す正しい正規表現とはどんなものだろうか。戻り読みが使える環境なら、否定戻り読みを使うのが簡単だと思う。 irb> my_answer = /^[-a-z0-9_][-a-z0-9_.]*(?&#60;!xyz)$/ => /^[-a-z0-9_][-a-z0-9_.]*(?&#60;!xyz)$/ irb> my_answer =~ "a_xyz" => nil irb> my_answer =~ "xyz" => nil irb> my_answer =~ "a" => 0 irb> my_answer =~ "abcdef" => 0 irb> my_answer =~ "abc_xyz_def" => 0 戻り読みが使えないとなると……ちょっと思いつかない。条件式を2つに分けるしかないだろうか。 ひっくり返して「xyzで始まってはいけない」にすると、否定先読みを使うことになる。例えば xyz で始まらない単語文字列なら ^(?!xyz)\w+$ さらに厳しくして「xyzではない」にするとどうだろう。…これは先読み/戻り読みだけでは無理かな？長さの条件も加えて ^\w{4,}$&#124;^(?!xyz)\w+$ といったところか。まあいずれにせよ、実際に使う機会は稀だろうが。 ちなみに件の製品は戻り読みが使えない glibc の [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwp.serpere.info%252Farchives%252F477%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22%E3%80%8C%E6%9C%AB%E5%B0%BE%E3%81%8Cxyz%E3%81%A7%E7%B5%82%E3%82%8F%E3%81%A3%E3%81%A6%E3%81%AF%E3%81%84%E3%81%91%E3%81%AA%E3%81%84%E3%80%8D%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%22%20%7D);"></div>
<p>とあるソフトウェア製品での出来事。</p>
<p>あるバグフィックス・アップデートを適用して以来、それまでは問題なかった入力値でValidation Errorが出るようになった。丸一日調べ回った結果、以前は</p>
<pre>
^[a-z0-9_\-][a-z0-9_\.\-]*$
</pre>
<p>だった入力チェックの正規表現が、</p>
<pre>
^[a-z0-9_\-][a-z0-9_\.\-]*[^x][^y][^z]$
</pre>
<p>に変わったため、と判明した（xyzは架空）。どうやら「末尾がxyzで終わってはいけない」という条件を追加したかったようだが、この正規表現は完全に誤りだといえる。これだと最低でも4文字以上ないとマッチしないし、&#8217;boxes&#8217;のような正当なはずの文字列にもマッチしないし、逆に&#8217;a+:^&#8217;のような不正であるべき文字列にマッチしてしまう。</p>
<p>では「末尾がxyzで終わってはいけない」を表す正しい正規表現とはどんなものだろうか。戻り読みが使える環境なら、否定戻り読みを使うのが簡単だと思う。</p>
<pre>
irb> my_answer = /^[-a-z0-9_][-a-z0-9_.]*(?&lt;!xyz)$/
=> /^[-a-z0-9_][-a-z0-9_.]*(?&lt;!xyz)$/
irb> my_answer =~ "a_xyz"
=> nil
irb> my_answer =~ "xyz"
=> nil
irb> my_answer =~ "a"
=> 0
irb> my_answer =~ "abcdef"
=> 0
irb> my_answer =~ "abc_xyz_def"
=> 0
</pre>
<p>戻り読みが使えないとなると……ちょっと思いつかない。条件式を2つに分けるしかないだろうか。</p>
<p>ひっくり返して「xyzで始まってはいけない」にすると、否定先読みを使うことになる。例えば xyz で始まらない単語文字列なら</p>
<pre>
^(?!xyz)\w+$
</pre>
<p>さらに厳しくして「xyzではない」にするとどうだろう。…これは先読み/戻り読みだけでは無理かな？長さの条件も加えて</p>
<pre>
^\w{4,}$|^(?!xyz)\w+$
</pre>
<p>といったところか。まあいずれにせよ、実際に使う機会は稀だろうが。</p>
<p>ちなみに件の製品は戻り読みが使えない glibc の regex を使っていたので、諦めてアップデート前の形に戻した。</p>

]]></content:encoded>
			<wfw:commentRss>http://wp.serpere.info/archives/477/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
