使用正则表达式来剪切字符串以特定字符开头?

时间:2012-06-20 17:58:53

标签: python regex

我正在处理一个平面文件,其中包含逐行格式的数据,如此

... blah blah blah | sku: 01234567 | price: 150 | ... blah blah blah

我想提取sku字段,它是8个字符长的数字。但是,我不确定是否应该使用split或regex,我不擅长在python中使用正则表达式。

5 个答案:

答案 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' sku1sku2sku-spsku-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'}

可能希望修剪一些多余的领先空间