微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

shlex.split() :如何在子字符串周围保留引号而不被子字符串中的空格分割?

如何解决shlex.split() :如何在子字符串周围保留引号而不被子字符串中的空格分割?

我希望输入字符串 "add [7,8,9+5,'io open'] 7&4 67"['add',"[7,'io open']",'7&4','67'] 一样拆分,即在行内,字符串必须保留在引号内并且根本不能拆分,否则需要基于空格的拆分,像这样:

>>> import shlex
>>> shlex.split("add [7,\\'io\\ open\\'] 7&4 67")
['add','67']

但是如果可能的话,用户不应该使用 \\,至少不要用于引号,但如果可能的话也不要用于字符串中的空格。

如上所示的函数 break_down() 会是什么样的?我尝试了以下操作,但它不处理字符串中的空格:

>>> import shlex
>>> def break_down(ln) :
...     ln = ln.replace("'","\\'")
...     ln = ln.replace('"','\\"')
...     # User will still have to escape in-string whitespace
...     return shlex.split(ln) # Note : Can't use posix=False; will split by in-string whitespace and has no escape seqs
...
>>> break_down("add [7,'io\\ open'] 7&4 67")
['add','67']
>>> break_down("add [7,'io open'] 7&4 67")
['add','io","open']",'67']

也许有更好的函数/方法/技术可以做到这一点,我对整个标准库还不是很有经验。或者我可能只需要编写一个自定义split()

编辑 1:进展

>>> def break_down(ln) :
...     ln = r"{}".format(ln) # escape sequences don't require \\
...     ln = ln.replace("'",r"\'")
...     ln = ln.replace('"',r'\"')
...     return shlex.split(ln)

所以现在用户只需要使用一个 \ 来转义任何引号/空格等,有点像他们在 shell 中所做的那样。看起来可行。

解决方法

我通过编写自定义词法系统(有点)解决了这个问题。

我决定使用 re,因为无论如何代码都大量使用 re,并且在 this reddit comment 的帮助下,已经解决了这个问题:

def lex(ln):
    ln = ln.split('#')[0] # Strip comments
    
    tkn_delims,relst = '\'\'""{}()[]',[] # Edit tkn_delims to add more delimiters  
    for i in range(0,len(tkn_delims),2):
        # Add regex for delimiter
        relst.append(r'\{0}[^{1}]*\{1}'.format(tkn_delims[i],tkn_delims[i+1])) 
    regex = '|'.join(relst) + r'|\S+' # Build regex
    
    import re
    return re.findall(regex,ln)

编辑:感谢@furas 的评论:“第一反应:你不能在参数中使用 #...”,代码编辑为仅在 {{1} 时识别评论的开始} 显示为 token 的第一个元素。因此:

  • # 词法到 <command> '#...' ['#...#']
  • ['command',"'#...'","['#...#']"]<command> '...' # does xyz 词法 <command> '...' #does xyz

已编辑['<command>',"'...'"]

lex()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。