14

たとえば、パターン「\section」がテキスト「abcd\sectiondefghi」に含まれているかどうかを知りたいとします。もちろん、私はこれを行うことができます:

import re

motif = r"\\section"
txt = r"abcd\sectiondefghi"
pattern = re.compile(motif)
print pattern.findall(txt)

それは私が欲しいものを私に与えるでしょう。ただし、新しいテキストで新しいパターンを見つけたいと思うたびに、コードを変更する必要があり、面倒です。したがって、次のように、より柔軟なものを書きたいと思います ( test.py):

import re
import sys

motif = sys.argv[1]
txt = sys.argv[2]
pattern = re.compile(motif)
print pattern.findall(txt)

次に、次のようにターミナルで実行します。

python test.py \\section abcd\sectiondefghi

ただし、それは機能しません (私は を使用するのが嫌い\\\\sectionです)。

それで、ユーザー入力(端末またはファイルから)をPythonの生の文字列に変換する方法はありますか?または、ユーザー入力から正規表現パターンのコンパイルを行うより良い方法はありますか?

どうもありがとうございました。

4

3 に答える 3

27

re.escape()入力テキストが正規表現でリテラル テキストとして扱われるようにするために使用します。

pattern = re.compile(re.escape(motif))

デモ:

>>> import re
>>> motif = r"\section"
>>> txt = r"abcd\sectiondefghi"
>>> pattern = re.compile(re.escape(motif))
>>> txt = r"abcd\sectiondefghi"
>>> print pattern.findall(txt)
['\\section']

re.escape()すべての非英数字をエスケープします。そのような各文字の前にバックスラッシュを追加します:

>>> re.escape(motif)
'\\\\section'
>>> re.escape('\n [hello world!]')
'\\\n\\ \\[hello\\ world\\!\\]'
于 2013-07-24T09:42:19.327 に答える
2

明確にするために、検索するもの(例では「\セクション」)は正規表現またはリテラル文字列であるはずですか?後者の場合、reモジュールは実際にはタスクに適したツールではありません。検索文字列needleとターゲット文字列を指定すると、次のhaystackことができます。

# is it in there
needle in haystack

# how many copies are there
n = haystack.count(needle)
python test.py \\section abcd\sectiondefghi
# where is it
ix = haystack.find(needle)

これらはすべて、正規表現ベースのバージョンよりも効率的です。

re.escapeは、実行時にリテラル フラグメントをより大きな正規表現に挿入する必要がある場合にも役立ちますが、最終的にre.compile(re.escape(needle)).

編集: ここでの本当の問題は、Python や生の文字列とは何の関係もないシェルのエスケープ ルールにあるのではないかと疑い始めています。つまり、次のように入力した場合:

python test.py \\section abcd\sectiondefghi

Unix スタイルのシェルに変換すると、"\section" の部分は、Python が認識する前に、シェルによって "\section" に変換されます。これを修正する最も簡単な方法は、エスケープ解除をスキップするようにシェルに指示することです。これは、引数を一重引用符で囲むことで実行できます。

python test.py '\\section' 'abcd\sectiondefghi'

比較対照:

$ python -c "import sys; print ','.join(sys.argv)" test.py \\section abcd\sectiondefghi
-c,test.py,\section,abcdsectiondefghi

$ python -c "import sys; print ','.join(sys.argv)" test.py '\\section' 'abcd\sectiondefghi'
-c,test.py,\\section,abcd\sectiondefghi

repr(さらに混乱を避けるために、ここでは結合された文字列で明示的に print を使用しています...)

于 2013-07-24T11:09:43.617 に答える
2

optparseこれを行う 1 つの方法は、またはのような引数パーサーを使用することargparseです。

コードは次のようになります。

import re
from optparse import OptionParser

parser = OptionParser()
parser.add_option("-s", "--string", dest="string",
                  help="The string to parse")
parser.add_option("-r", "--regexp", dest="regexp",
                  help="The regular expression")
parser.add_option("-a", "--action", dest="action", default='findall',
                  help="The action to perform with the regexp")

(options, args) = parser.parse_args()

print getattr(re, options.action)(re.escape(options.regexp), options.string)

私の使用例:

> code.py -s "this is a string" -r "this is a (\S+)"
['string']

あなたの例を使用して:

> code.py -s "abcd\sectiondefghi" -r "\section"
['\\section'] 
# remember, this is a python list containing a string, the extra \ is okay.
于 2013-07-24T09:47:05.190 に答える