0

ある文字列の間にある文字列を検索したい。例えば、

\start

\problem{number}
\subproblem{number}

/* strings that I want to get */

\subproblem{number}

/* strings that I want to get */

\problem{number}
\subproblem{number}
       ...
       ...
\end

具体的には、問題番号とサブ問題番号、およびその間の文字列を取得したいと思います。

なんとなく次のような表現を思いついた

'(\\problem{(.*?)}\n)? \\subproblem{(.*?)} (.*?) (\\problem|\\subproblem|\\end)'

でも思った通りに動かないようです。この表現の何が問題になっていますか?

4

3 に答える 3

2

これです:

(?:\\problem\{(.*?)\}\n)?\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)

私のために3つの一致を返します:

マッチ1:

group 1: "number"
group 2: "number"
group 3: "/* strings that I want to get */"

マッチ2:

group 1: null
group 2: "number"
group 3: "/* strings that I want to get */"

マッチ3:

group 1: "number"
group 2: "number"
group 3: "       ...\n       ..."

ただし、2つのステップで解析したいと思います。

まず、以下を使用して問題の番号(グループ1)とコンテンツ(グループ2)を見つけます。

\\problem\{(.*?)\}\n(.+?)\\end

次に、以下を使用して、そのコンテンツ内のサブ問題の番号(グループ1)とコンテンツ(グループ2)を見つけます。

\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)
于 2013-01-26T01:28:32.690 に答える
2

質問が本当に「この式の何が問題になっていますか?」である場合、答えは次のとおりです。

  • 改行を。と一致させようとしてい.*?ます。それが機能する必要があります(?s)
  • 正規表現の中央に明示的なスペースと改行があり、ソーステキストに対応する文字がありません。それが機能する必要があります(?x)

それは表現で間違っているすべてではないかもしれません。しかし、を追加し(?sx)、それを生の文字列に変換し(Pythonの引用符と正規表現の引用符を適切に混合することを自分自身が信頼していないため)、削除すると、次の\nようになります。

r'(?sx)(\\problem{(.*?)}? \\subproblem{(.*?)} (.*?)) (\\problem|\\subproblem|\\end)'

これは、0ではなく2つの一致を返します。これは、おそらく、機能する正規表現への最小の変更です。

ただし、「これを解析するにはどうすればよいですか?」という質問の場合、「既存の試みの何が問題になっていますか?」ではなく、implのソリューションの方が理にかなっていると思います(正規表現を使用してTeXを解析するという点にも同意します。悪い考え)-または、さらに良いことに、正規表現のように2つのステップでそれを実行します。


正規表現を使用してTeXを解析するのが適切でない場合、TeXを解析するためにどのような方法を提案しますか?

まず、一般的な経験則として、自分で問題を解決するための正規表現を記述できない場合、それを理解するのに苦労するため、正規表現で解決したくありません。今から数ヶ月。時々それを部分式に分解したり(?x)、コメントを使ってロードしたりしますが、通常は別の方法を探します。

etreeさらに重要なのは、言語を消費して、たとえばXMLの場合のように、歩いて検索できるツリー(または適切なもの)を提供できる実際のパーサーがある場合、すべてのソリューションの90%が得られることです。あなたがその言語を扱う際に思いつく問題。迅速で汚い正規表現(特に自分で書くことができない正規表現)では、次の問題を解決する方法の10%しか得られません。そして、多くの場合、今日問題が発生した場合は、今後数か月以内にさらに多くの問題が発生する予定です。

では、PythonでのTeXの優れたパーサーは何ですか?正直なところ、わかりません。私はそれをする何かを知っているscipy/matplotlib持っているので、私はおそらく最初にそこを見るでしょう。それ以外にも、Google、PyPI、そしておそらくtex.stackexchange.comをチェックしてください。検索で最初に表示されるのはTexcallerplasTeXです。それらがどれほど優れているか、またはそれらがあなたのユースケースに適しているかどうかはわかりませんが、チュートリアルをざっと読んで見つけるのにそれほど時間はかからないはずです。

そこに何もないことが判明し、たとえば正規表現に対して自分で何かを書くことになった場合、pyparsingそれはより難しい選択です。一部の言語では、気になるサブセットだけを定義し、残りを巨大な未解釈のトークンとして残すのは非常に簡単です。この場合、実際のパーサーは正規表現と同じくらい簡単なので、そのようにした方がよいでしょう。他の言語では、何か便利なことをする前に構文の半分を処理する必要があるので、私も試しません。どちらに行くかを決める前に、少し時間をかけて考え、両方の方法を試してみる必要があります。

于 2013-01-26T01:28:54.147 に答える
2

TeXはかなり複雑で、正規表現を使用して解析することについてどう思うかわかりません。

とはいえ、正規表現には2つの問題があります。

  • すべての空白を消費する必要があるスペース文字を使用しています
  • 最終グループに先読みアサーションを使用して、それが食べ尽くされないようにする必要があります(次回の正規表現の開始時に一致させる必要があるため)

これを試してみてください:

>>> v
'\\start\n\n\\problem{number}\n\\subproblem{number}\n\n/* strings that I want to get */\n\n\\subproblem{number}\n\n/* strings that I want to get */\n\n\\problem{number}\n\\subproblem{number}\n       ...\n       ...\n\\end\n'
>>> re.findall(r'(?:\\problem{(.*?)})?\s*\\subproblem{(.*?)}\s*(.*?)\s*(?=\\problem{|\\subproblem{|\\end)', v, re.DOTALL)
[('number', 'number', '/* strings that I want to get */'), ('', 'number', '/* strings that I want to get */'), ('number', 'number', '...\n       ...')]
于 2013-01-26T01:22:14.327 に答える