web-dev-qa-db-ja.com

負の先読み正規表現

「foo.htm」で終わる場合を除き、「。htm」で終わるすべての文字列に一致させたい。私は一般的に正規表現にはまともですが、ネガティブな先読みには困惑しています。なぜこれが機能しないのですか?

/(?!foo)\.htm$/i.test("/foo.htm");  // returns true. I want false.

代わりに何を使うべきですか? 「ネガティブな外観が必要だと思う後ろに「式(JavaScriptがそのようなことをサポートしている場合、そうではないことを知っています)。

62
gilly3

問題は本当に簡単です。これはそれを行います:

/^(?!.*foo\.htm$).*\.htm$/i

92
ridgerunner

あなたが説明していること(あなたの意図)はマイナス後読みであり、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 
18
Nicole

前述のように、JavaScriptはネガティブな後読みアサーションをサポートしていません。

しかし、あなたはワークロードを使用することができます:

/(foo)?\.htm$/i.test("/foo.htm") && RegExp.$1 != "foo";

これは、.htmで終わるすべてに一致しますが、"foo"に一致する場合はRegExp.$1foo.htmを格納するため、個別に処理できます。

2
Floern

前述のRenesisのように、「lookbehind」はJavaScriptでサポートされていないため、2つの正規表現を組み合わせて使用​​することもできます。

!/foo\.htm$/i.test(teststring) && /\.htm$/i.test(teststring)
2
petho

おそらく、この答えは必要以上に少し遅れて届きましたが、誰かが同じ問題に出くわす場合に備えてここに残しておきます(この質問が出されてから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エンジンに渡すメッセージは、次のようなものです。

次の文字列をすべてこの文字列で見つけてください。

  • 他のテキスト(単語など)から分離。
  • 英語のアルファベット、アンダースコア、ハイフン、ドット、または数字の1つ以上の文字で構成されます。
  • 「.htm」で終わります。
  • それとは別に、「。htm」の前のシーケンスの部分は「foo」以外の可能性があります。
1
Igor Bykov

String.prototype.endsWithES6

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

);
1
Roko C. Buljan

/(.|..|.*[^f]..|.*f[^o].|.*fo[^o])\.htm$/のようなものでネガティブな後読みをエミュレートできますが、プログラムによるアプローチの方が良いでしょう。

0
ngn