在python中查找字符串中模式的所有实例

时间:2014-01-20 15:42:14

标签: python regex

我正在为python中的帐户存储工具编写一个命令解析器,并且基本功能很好。

用户在程序解释器(不是命令行参数)中输入命令,如[+] -u peter -e myemail@email.com -p password

我的问题出现在上面命令的一个用例中,我一直在“ - ”上拼写字符串以获得类似['u peter', 'e myemail@email.com', 'p password']的列表,但如果用户的用户名中有“ - ”,该怎么办? ,这样的电子邮件或密码-p pass-word我最终会以['u peter', 'e myemail@email.com', 'p pass', 'word']

结束

我一直在调查正则表达式以分割命令但却无法确定它。到目前为止,我已经得到了这个\-[a-z][^\-]*,但它也将“pass-word”样式参数分开。

有没有人知道正确或聪明的方式来做到这一点,因为在这个阶段我抓着吸管。

谢谢, 彼得

*编辑*

因此,对于最符合我需求的解决方案,我遵循了@ samkhan13的回答并放弃了正则表达式,这要归功于你们许多人给出的建议。这是我的解决方案,只要用户确实有一个被密码中的空格包围的命令,就可以使用我的用例,如果他们这样做,他们就可以使用更好的软件了!

def parseString(userInput):
    poslist = [userInput.find(' -u '),
               userInput.find(' -e '),
               userInput.find(' -p '),
               userInput.find(' -s '),
               userInput.find(' -g ')]
    poslist.sort()
    poslist = filter(lambda a: a != -1, poslist)
    text = []
    for j in range(poslist.__len__()-1):
        text.append(userInput[poslist[j]+2:poslist[j+1]])

    text.append(userInput[poslist[poslist.__len__()-1]+2:])
    return text

输入>> ' -e myemail@email.com -p pa"-ussword'

输出>> ['e myemail@email.com ', 'p pa"-ussword']

*编辑*

并且是一个处理未知命令的正则表达式

def parseString(userInput):
    poslist = []
    text = []
    p = re.compile("\s-[a-z]\s") #searches for unix style commands
    for m in p.finditer(userInput):
        poslist.append(m.start())

    for j in range(poslist.__len__()-1):
        text.append(userInput[poslist[j]+2:poslist[j+1]])

    text.append(userInput[poslist[poslist.__len__()-1]+2:])
    return text

输入>> ' -e myemail@email.com -p pa"-ussword -x pmck'

输出>> ['e myemail@email.com', 'p pa"-ussword', 'x pmck']

4 个答案:

答案 0 :(得分:0)

这种密码模式怎么样:((^|\s)-p\s)[^\s$]+?它适用于pass-word

答案 1 :(得分:0)

此模式

-[^ ].*?(?:'.*?'|".*?")?(?:(?= -\S)|$)

即使参数符合此模式,即使密码中有-,也会匹配参数:-p "bar -u foo"

它能解决你的问题吗?

警告

正如@shenshin指出的那样,-p "a "" - b"不匹配。很多奇怪的案例都不会在这里被抓住,快速正则表达式的答案可能是一个“quickfix”,但对于更强大和更安全的解决方案,你可能不得不转向另一个工具。

答案 2 :(得分:0)

如果您的用例是特定的,您可以一起避免正则表达式。

def parseString(userInput):
    namePosition = userInput.find('-u')
    emailPosition = userInput.find('-e')
    passwordPosition = userInput.find('-p')

    if namePosition != -1 and emailPosition != -1 and passwordPosition != -1:
        nameText = userInput[namePosition+1:emailPosition] # will look like 'u peter'
        emailText = userInput[emailPosition+1:passwordPosition]
        passwordText = userInput[passwordPosition+1:]
        return [nameText,emailText,passwordText]
    else:
        print 'improper number or type of parameters given as input'

someText = '-u peter -e myemail@email.com -p password'

parsedText = parseString(someText)
print parsedText

如果您怀疑应允许用户使用-u-e-p或其他-x输入各种文本,请尝试修改上述示例}

答案 3 :(得分:0)

这可能比你要求的要多得多。

它并不复杂。每个部分都是一样的 唯一的区别是命令字母u,e,p。

表达式仅匹配其中的命令,因此其他表达式可以混合但不匹配 命令可以是任何顺序,甚至根本不存在。
每个命令都被严格删除,因此它们的值中可以有连字符/空格 仅捕获值,修剪前导/尾随空白。

<强>编辑
要添加更多命令,只需将段复制到底部并更改命令字母即可。假设所有小写字母a-z都是命令,并且必须采用严格的形式才能被视为命令。否则它的部分价值。

多数民众赞成,我在Perl中测试过,就像一个魅力。如果您想查看该测试用例,请告诉我。

 # ^(?=.*(?:^\s*|\s-)u\s+((?:[^\s-]+|(?!\s*-[a-z]\s|\s*$)[\s-]+)*))?(?=.*(?:^\s*|\s-)e\s+((?:[^\s-]+|(?!\s*-[a-z]\s|\s*$)[\s-]+)*))?(?=.*(?:^\s*|\s-)p\s+((?:[^\s-]+|(?!\s*-[a-z]\s|\s*$)[\s-]+)*))?


 ^ 
 (?=
      .* 
      (?: ^ \s* | \s - )
      u \s+ 
      (                             # (1)
           (?:
                [^\s-]+ 
             |  (?! \s* - [a-z] \s | \s* $ )
                [\s-]+ 
           )*
      )
 )?
 (?=
      .* 
      (?: ^ \s* | \s - )
      e \s+ 
      (                             # (2)
           (?:
                [^\s-]+ 
             |  (?! \s* - [a-z] \s | \s* $ )
                [\s-]+ 
           )*
      )
 )?
 (?=
      .* 
      (?: ^ \s* | \s - )
      p \s+ 
      (                             # (3)
           (?:
                [^\s-]+ 
             |  (?! \s* - [a-z] \s | \s* $ )
                [\s-]+ 
           )*
      )
 )?

<强> EDIT2
这是Perl中的测试用例 如果需要,您可以命名捕获组。在样本中,它们被编号 示例:

 (?=
      .* 
      (?: ^ \s* | \s - )
      p \s+ 
      (?P<password>
           (?:
                [^\s-]+ 
             |  (?! \s* - [a-z] \s | \s* $ )
                [\s-]+ 
           )*
      )
 )?

测试用例

 $/ = undef;
 my $str = <DATA>;

 if ( $str =~ /^(?=.*(?:^\s*|\s-)u\s+((?:[^\s-]+|(?!\s*-[a-z]\s|\s*$)[\s-]+)*))?(?=.*(?:^\s*|\s-)e\s+((?:[^\s-]+|(?!\s*-[a-z]\s|\s*$)[\s-]+)*))?(?=.*(?:^\s*|\s-)p\s+((?:[^\s-]+|(?!\s*-[a-z]\s|\s*$)[\s-]+)*))?/s)
 {
     print "user = '$1'\n";
     print "email = '$2'\n";
     print "password = '$3'\n";

 }
 __DATA__

 This string has commands -x, -e, -y, -p, -u commands it it 

   -x XVA-LUE -e  asdf-myemail@-email.com -y YVA-LUE -p pa'-#@-p,s"sword -z ZVA-LUE -u  Pe-ter

输出&gt;&gt;

 user = 'Pe-ter'
 email = 'asdf-myemail@-email.com'
 password = 'pa'-#@-p,s"sword'