「foo.htm」で終わる場合を除き、「。htm」で終わるすべての文字列に一致させたい。私は一般的に正規表現にはまともですが、ネガティブな先読みには困惑しています。なぜこれが機能しないのですか?
/(?!foo)\.htm$/i.test("/foo.htm"); // returns true. I want false.
代わりに何を使うべきですか? 「ネガティブな外観が必要だと思う後ろに「式(JavaScriptがそのようなことをサポートしている場合、そうではないことを知っています)。
問題は本当に簡単です。これはそれを行います:
/^(?!.*foo\.htm$).*\.htm$/i
あなたが説明していること(あなたの意図)はマイナス後読みであり、Javascriptは後読みをサポートしていません。
先読みは、配置されているキャラクターから先読みします— .
の前に配置しました。そのため、実際に「.htm
で終わるものはすべて、その位置で始まる最初の3文字(.ht
)がfoo
ではない限り」と言っています。 。
通常、ネガティブな後読みの代わりは、必要以上に一致させ、実際に必要な部分のみを抽出することです。これはハッキーです。あなたの正確な状況次第では、おそらく他の何かを思いつくことができますが、次のようなものです:
// Checks that the last 3 characters before the dot are not foo:
/(?!foo).{3}\.htm$/i.test("/foo.htm"); // returns false
前述のように、JavaScriptはネガティブな後読みアサーションをサポートしていません。
しかし、あなたはワークロードを使用することができます:
/(foo)?\.htm$/i.test("/foo.htm") && RegExp.$1 != "foo";
これは、.htm
で終わるすべてに一致しますが、"foo"
に一致する場合はRegExp.$1
にfoo.htm
を格納するため、個別に処理できます。
前述のRenesisのように、「lookbehind」はJavaScriptでサポートされていないため、2つの正規表現を組み合わせて使用することもできます。
!/foo\.htm$/i.test(teststring) && /\.htm$/i.test(teststring)
おそらく、この答えは必要以上に少し遅れて届きましたが、誰かが同じ問題に出くわす場合に備えてここに残しておきます(この質問が出されてから7年、6か月後)。
現在、後読みはECMA2018標準に含まれており、少なくとも最新バージョンのChromeでサポートされています。ただし、パズルを使用してもしなくても解決できます。
ネガティブな先読みによるソリューション:
let testString = `html.htm app.htm foo.tm foo.htm bar.js 1to3.htm _.js _.htm`;
testString.match(/\b(?!foo)[\w-.]+\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]
ネガティブな後読みのソリューション:
testString.match(/\b[\w-.]+(?<!foo)\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]
(技術的に)ポジティブな先読みを伴うソリューション:
testString.match(/\b(?=[^f])[\w-.]+\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]
等.
これらすべてのRegExpは、JSエンジンに異なる方法で同じことを伝えます。JSエンジンに渡すメッセージは、次のようなものです。
次の文字列をすべてこの文字列で見つけてください。
String.prototype.endsWith(ES6 )
console.log( /* !(not)endsWith */
!"foo.html".endsWith("foo.htm"), // true
!"barfoo.htm".endsWith("foo.htm"), // false (here you go)
!"foo.htm".endsWith("foo.htm"), // false (here you go)
!"test.html".endsWith("foo.htm"), // true
!"test.htm".endsWith("foo.htm") // true
);
/(.|..|.*[^f]..|.*f[^o].|.*fo[^o])\.htm$/
のようなものでネガティブな後読みをエミュレートできますが、プログラムによるアプローチの方が良いでしょう。