67

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

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

代わりに何を使うべきですか?「ネガティブルックビハインド」式が必要だと思います(JavaScriptがそのようなことをサポートしている場合、それはサポートされていません)。

4

7 に答える 7

98

問題は実に単純です。これはそれを行います:

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

于 2011-07-27T23:04:47.470 に答える
18

あなたが説明しているのは (あなたの意図) は否定的な読みであり、Javascript は後読みをサポートしていません。

先読みは、それらが配置されている文字から楽しみにしています — そしてあなたはそれを . の前に配置しました.。したがって、実際には、「その位置で始まる最初の 3 文字 ( ) でない.htm限り、で終わるものは何でも」と言っていますが、これは常に真です。.htfoo

通常、否定的な後読みの代わりに、必要以上に一致させて、実際に必要な部分だけを抽出します。これはハックであり、正確な状況に応じて、おそらく別のものを思い付くことができますが、次のようなものです:

// Checks that the last 3 characters before the dot are not foo:
/(?!foo).{3}\.htm$/i.test("/foo.htm"); // returns false 
于 2011-07-27T22:20:55.190 に答える
2

前述のとおり、JavaScript は否定的な後読みアサーションをサポートしていません。

ただし、回避策を使用できます。

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

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

于 2011-07-27T22:25:57.860 に答える
2

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

!/foo\.htm$/i.test(teststring) && /\.htm$/i.test(teststring)
于 2011-07-27T22:26:06.117 に答える
1

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

);

于 2016-03-22T22:33:26.317 に答える
1

おそらく、この回答は必要よりも少し遅れて到着しましたが、誰かが同じ問題に遭遇した場合に備えて、ここに残しておきます (この質問が行われてから 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」以外の何かである可能性があります。
于 2019-02-14T03:06:41.533 に答える
0

のようなもので否定的な後読みをエミュレートできます /(.|..|.*[^f]..|.*f[^o].|.*fo[^o])\.htm$/が、プログラムによるアプローチの方が優れています。

于 2011-07-27T22:31:03.873 に答える