このように、行ごとの形式でデータを含むフラットファイルを処理しています
... blah blah blah | sku: 01234567 | price: 150 | ... blah blah blah
sku フィールドを抽出したいのですが、それは 8 文字の長さの数字です。ただし、分割または正規表現を使用する必要があるかどうかはわかりません。Pythonで正規表現を使用するのはあまり得意ではありません。
sku
あなたの値が常に8文字の長さであり、常に「sku」が前にあり、おそらく「:」がいくつかあると仮定すると(間にスペースがあってもなくても)、正規表現を使用しますr'sku[\s:]*(\d{8})'
::
>>> import re
>>> string = '... | sku: 01234567 | price: 150 | ... '
>>> re.findall(r'sku[\s:]*(\d{8})', string)[0]
'01234533'
値のsku
長さが可変の可能性がある場合は、次を使用してください: r'sku[\s:]*(\d*)'
:
>>> import re
>>> string = '... | sku: 01234 | price: 150 | sku: 99872453 | blah blah ... '
>>> re.findall(r'sku[\s:]*(\d*)', string)[0]
'01234'
>>> re.findall(r'sku[\s:]*(\d*)', string)[1]
'99872453'
編集
sku1
「sku」の後に 、sku2
、sku-sp
、sku-18
またはなどの他の文字が続く場合はsku_anything
、それを試すことができます。
>>> re.findall(r'sku\D*(\d*)', string)[0]
これは、次のものとまったく同じです。
>>> re.findall(r'sku[^0-9]*([0-9]*)', string)[0]
それは非常に一般的です。で始まりsku
、その後に任意の数の非 10 進文字 ( \D*
、または[^0-9]*
)、およびいくつかの 10 進文字 ( \d*
、または[0-9]*
) が続くものと一致します。後者を返します (未定の長さの 10 進文字の文字列)。
さて、これらの表現を構築するために使用したものは何を意味しますか:
*
: 単一の文字または文字のクラスに続く場合、この記号は、式がその後に続く文字またはクラスの未定の数に一致することを*
意味します (「0 または一部」を+
意味し、「少なくとも 1 つ」を?
意味し、「0 または 1 」を意味します)。 」)。{}
同じように使用されます。それらは文字または文字のクラスに従います。それらは数量詞でもあります。と言うと、正確に 4 つの 'c' で構成される任意の文字列に一致します。1 ~ 6 個の「c」で構成される任意の文字列に一致するという場合。*
+
?
c{4}
c{1,6}
[]
: 文字のクラスを定義します。[abc]
'a'、'b'、または 'c' のいずれかの文字を意味します。小文字[a-z]
のいずれかを意味します。、大文字のいずれか、小文字と大文字のいずれか、[0-9] 小数点文字のいずれか。小数をドット、またはコンマ、プラス、マイナス、および「e」と一致させたい場合 (たとえば、指数の場合)、単に.[A-Z]
[a-zA-Z]
[0-9,\.+-e]
^
内部 - で定義され[]
、「逆クラス」、クラス以外のすべてを意味します。次に、[^0-9]
小数点[^a-z]
以外の文字、小文字以外の文字などを意味します。これらは、正規表現の構文をより使いやすくするために、Python で事前定義されているクラスです。
\s
: 任意のスペーシング文字 (スペース、タブなど) に一致します。\d
: 任意の 10 進文字に一致します (0、1、2、3、4、5、6、7、8、9 ... これは[0-9]
、正規表現で文字クラスを表現する別の方法である と同等です)\D
: は任意の非[^0-9]
10 進文字と一致します ... これは、正規表現で除外された文字のクラスを表現する別の方法である と同等です。\S
:非スペーシング文字と一致します ...\w
: 任意の「単語文字」に一致します\W
:単語以外の文字と一致します()
いくつかのグループを定義します。それらには多くの用途があります。ここでfindall
、グループは、式によって返されるものを強調表示します...つまり。(\d{8})
or[0-9]{8}
は、式が一致する完全な文字列内の 8 つの 10 進文字の文字列のみを返すことを意味します。正規表現は非常に使いやすく、非常に便利です。それらができることとできないことをよく理解する必要があります(それらは通常の言語に限定されています。たとえば、ネストされたもののレベルを処理する必要がある場合、または文脈自由文法で定義された他の言語を処理する必要がある場合は、正規表現が勝ちました十分ではありません)。次のページをご覧になることをお勧めします。
次のようなものは、正確な間隔や位置に依存することなく、必要なことを達成するはずです。
>>> s = '... blah blah blah | sku: 01234567 | price: 150 | ... blah blah blah'
>>> match_obj = re.search(r'sku\s*:\s*(\d+)', s)
>>> match_obj.group(1)
'01234567'
メソッドを使用して一致オブジェクトにアクセスする前に.group()
、一致が実際に発生したことを確認する必要がありますif match_obj: # do something with match
。
私の意見では、split、「sku:」および「|」を使用する必要があります セパレータとして機能します:
s = "blah blah blah | sku: 01234567 | price: 150 | ... blah blah blah"
s.split("sku:")[1].split("|")[0]
これがチェックです:
s = "blah blah blah | sku: 01234567 | price: 150 | ... blah blah blah"
s1 = s.split("sku:")
if len(s1) == 2:
print s1[1].split("|")[0]
パイプで区切られたすべてのフィールドも(key:value)である場合は、必要でない限り、残りのデータを保持することもできます。すでに文字列を解析する必要があります...
s = "sku: 01234567 | price: 150"
dict( k.split(':') for k in s.split('|') )
# {sku': ' 01234567 ', ' price': ' 150'}
ただし、余分な先頭のスペースをトリミングしたい場合があります
文字列の 8 桁の数字がすべて SKU 番号である場合は、
re.findall(r"\b\d{8}\b", mystring)
単語境界アンカーにより、\b
より長い数字/単語内の 8 桁の部分文字列が一致しないことが保証されます。