4

Python で作成している JavaScript プリプロセッサに軽いマークダウン サポートを追加しようとしています。

ほとんどの場合は機能していますが、私が使用している正規表現が少し奇妙な動作をすることがあります。生の文字列とエスケープ シーケンスに関係があると思います。

正規表現は次のとおりです。(?<!\\)\"[^\"]+\"

はい、文字で始まる文字列のみに一致することは承知しています"。しかし、このプロジェクトは何よりも好奇心から生まれたので、今のところは我慢できます。

それを分解するには:

(?<\\)\"    # The group should begin with a quotation mark that is not escaped
[^\"]+      # and match any number of at least one character that is not a quotation mark (this is the biggest problem, I know)
\"          # and end at the first quotation mark it finds

そうは言っても、私は(明らかに)次のような問題にぶつかり始めています。

"This is a string with an \"escaped quote\" inside it"

「そのマークがエスケープされていない限り、引用符以外のすべて」と言う方法がよくわかりません。私は試した:

([^\"]|\\\")+     # a group of anything but a quote or an escaped quote

、しかしそれは非常に奇妙な結果につながります。

私はこれについてすべて間違っていると聞く準備ができています。簡単にするために、この正規表現は常に二重引用符 ( ") で開始および終了して、ミックスに別の要素を追加しないようにします。自分がこれまでに持っているものを本当に理解したいです。

ご協力ありがとうございます。

編集

正規表現のテストとして、次のコード (以下の unutbu のパターンを使用) を使用して、縮小された jQuery スクリプト内のすべての文字列リテラルを見つけようとしています。

STRLIT = r'''(?x)   # verbose mode
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    .*?        # non-greedy 1-or-more characters
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    ''' 
f = open("jquery.min.js","r")
jq = f.read()
f.close()
literals = re.findall(STRLIT,jq)

以下の回答は、ほぼすべての問題を修正します。発生するものは、jquery 独自の正規表現内にあり、これは非常にまれなケースです。このソリューションは、有効な JavaScript をマークダウン リンクとして誤認しなくなりました。これは実際の目標でした。

4

3 に答える 3

6

このアイデアを最初に見たのは... Jinja2 のソース コードですか? 後にマコに移植。

r'''(\"\"\"|\'\'\'|\"|\')((?<!\\)\\\1|.)*?\1'''

次のことを行います。

  • (\"\"\"|\'\'\'|\"|\')Python の開始引用符に一致します。これは、Python を解析するためのコードから取得されたものであるためです。おそらく、これらすべての引用タイプは必要ありません。
  • ((?<!\\)\\\1|.)一致: 1 回だけエスケープされた一致する引用符、またはその他の文字。その\\"ため、引き続き文字列の末尾として認識されます。
  • *?非貪欲に可能な限り多くのものに一致します。
  • そして\1、ちょうど終わりの引用です。

残念ながら\\\"、文字列の末尾として誤って検出されます。(テンプレート エンジンはこれを、文字列が存在するかどうかを確認するためだけに使用し抽出するためではありません。) これは、正規表現にはあまり適していない問題です。正規表現内に実際のコードを埋め込むことができるPerlで非常識なことをすることを除けば、PCREでもそれが可能かどうかはわかりません。私が間違っていることを証明したいのですが。:) キラーは(?<!...)constant -lengthである必要がありますが、終了引用符の前に偶数個のバックスラッシュがあることを確認する必要があります。

ほぼ正しいだけでなく、これを正しくしたい場合は、実際のパーサーを使用する必要があるかもしれません。パセリpyparsing、またはこれらのツールのいずれかを見てください。

編集:ちなみに、開始引用符の前にバックスラッシュがないことを確認する必要はありません。これは、JS (または Python) の文字列の外側では有効な構文ではありません。

于 2013-01-16T20:08:56.990 に答える
5

おそらく、次の 2 つの否定的なルック ビハインドを使用します。

import re

text = r'''"This is a string with an \"escaped quote\" inside it". While ""===r?+r:wt.test(r)?st.parseJSON(r)    :r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data" '''

for match in (re.findall(r'''(?x)   # verbose mode
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    .*?        # 1-or-more characters
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    ''', text)):
    print(match)

収量

"This is a string with an \"escaped quote\" inside it"
""
"data"

のクエスチョン マーク.+?は、パターンを非欲張りにします。非貪欲性により、最初のエスケープされていない二重引用符に遭遇したときにパターンが一致します。

于 2013-01-16T19:46:29.277 に答える
0

Using python, the correct regex matching double quoted string is:

pattern = r'"(\.|[^"])*"'

It describes strings starts and ends with ". For each character inside the two double quotes, it's either an escaped character OR any character expect ".

unutbu's ansever is wrong because for valid string "\\\\", cannot matched by that pattern.

于 2016-06-21T03:58:50.660 に答える