我正在处理一个平面文件,其中包含逐行格式的数据,如此
... blah blah blah | sku: 01234567 | price: 150 | ... blah blah blah
我想提取sku字段,它是8个字符长的数字。但是,我不确定是否应该使用split或regex,我不擅长在python中使用正则表达式。
答案 0 :(得分:3)
假设你的sku
值总是8个字符长,并且总是以'sku'开头,可能还有一些':'(中间有空格或不带空格),那么我会使用正则表达式:{ {1}}:
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*)'
修改强>
如果您的'sku'后跟其他一些字符,例如>>> 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
,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
或\D*
),以及一些十进制字符({{ 1}},或[^0-9]*
)。它将返回后者(一串未确定的十进制字符长度)。
现在,我用来构建这些表达式的东西是什么意思:
\d*
:当跟随单个字符或一类字符时,此符号表示该表达式将匹配其后跟的任何未定数量的字符或类([0-9]*
表示“0或某些” ,*
表示“至少一个”,*
表示“0或1”。+
的使用方式与?
,{}
和*
相同,即。他们追随一个角色或一类人物。他们也是量词。如果你说+
,它将匹配任何由4'c组成的字符串。如果您说?
,它将匹配由1到6'c'组成的任何字符串。c{4}
:定义一类字符。 c{1,6}
表示任何字符'a','b'或'c'。 []
表示任何小写字母。 [abc]
,任何大写字母,[a-z]
任何小写和大写字母,[0-9]任何小数字符。如果你想用小数点或逗号匹配小数,加号,减号和'e'(例如,对于指数),只需说[A-Z]
。[a-zA-Z]
- 用[0-9,\.+-e]
定义,表示'倒置类',除了类之外的所有内容。然后,^
表示除十进制字符以外的任何内容,[]
除小写字母外的任何内容,依此类推。依此类推。这些是在python中预定义的类,用于使正则表达式语法更友好:
[^0-9]
:将匹配任何间距字符(空格,制表等)[^a-z]
:将匹配任何小数字符(0,1,2,3,4,5,6,7,8,9 ......这相当于\s
,这是另一个在正则表达式中表达字符类的方法)\d
:将匹配任何非 - 十进制字符...这相当于[0-9]
,这是在正则表达式中表达排除的字符类的另一种方式。 \D
:将匹配任何非 -spacing字符... [^0-9]
:将匹配任何“字词”\S
:将匹配任何非字符字符\w
定义了一些群组。他们有很多用法。在\W
中,该组突出显示您希望通过表达式返回的内容...即。 ()
或findall
表示您希望表达式仅返回匹配完整字符串中8个十进制字符的字符串。正则表达式非常易于使用,非常有用。你只需要很好地理解它们可以做什么以及它们不能做什么(它们仅限于常规语言。例如,如果你需要处理嵌套事物的级别,或者使用无上下文语法定义的其他语言,那么正则表达式获胜够了。您可能希望查看以下页面:
答案 1 :(得分:1)
以下内容应该达到您的需要,而不依赖于确切的间距和位置:
>>> 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
。
答案 2 :(得分:0)
如果字符串中的所有8位数字都是SKU编号,则可以使用
re.findall(r"\b\d{8}\b", mystring)
\b
字边界锚点确保不会匹配较长数字/单词中的8位数字串。
答案 3 :(得分:0)
在我看来你应该使用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]
答案 4 :(得分:0)
如果所有管道分隔的字段也是(键:值),那么除非你需要它,否则你可能还要保留其余的数据 - 你已经不得不解析字符串...
s = "sku: 01234567 | price: 150"
dict( k.split(':') for k in s.split('|') )
# {sku': ' 01234567 ', ' price': ' 150'}
可能希望修剪一些多余的领先空间