用括号

时间:2017-03-30 14:31:28

标签: python regex

我有一个字符串如下:

oldString="this is my {{string-d}}" => "this is my {{(string-d)}}"
oldString2="this is my second{{ new_string-d }}" => "this is my second{{ (new_string-d) }}"
oldString2="this is my second new_string-d " => "this is my second (new_string-d) "
oldString2="this is my second new[123string]-d " => "this is my second (new[123string]-d) "

每当我在其后面和附加的单词之前看到“-d”时,我想添加括号。

我编写了一个代码,在字符串中查找模式“-d”,并在“-d”之前找到3个分区之后对字符串进行分区,在“-d”和“-d”本身之后然后我检查在“-d”之前阻塞,直到找到空格或“{”并停止并添加括号。我的代码看起来像这样: 附:我有许多文件,我从他们那里读取并尝试修改字符串,上面的例子仅用于演示我正在尝试做的事情。

   if ('-d') in oldString:
    p = oldString.partition('-d')
    v = p[p.index('-d')-1]
    beforeString=''
    for i in reversed(v):
        if i != ' ' or i != '{':
            beforeString=i+beforeString 
            indexNew = v.index(i)
    outPutLine = v[:indexNew]+'('+v[indexNew:]
    newString = outPutLine + '-d' + ' )'
    print newString

运行代码的结果将是:

newString = "(this is my {{string-d )"

你可以看到起始括号在“this”之前而不是在“string”之前,为什么会发生这种情况?此外,我不确定这是否是最好的方式来做这种查找和替换任何建议将不胜感激。

2 个答案:

答案 0 :(得分:3)

>>> import re
>>> oldString = "this is my {{string-d}}"
>>> oldString2 = "this is my second{{ new_string-d }}"
>>> re.sub(r"(\w*-d)", r"(\1)", oldString)
'this is my {{(string-d)}}'
>>> re.sub(r"(\w*-d)", r"(\1)", oldString2)
'this is my second{{ (new_string-d) }}'

请注意,这与“单词”匹配,假设单词仅由字母,数字和下划线组成。

以下是对所发生情况的更全面细分:

  • 字符串文字前面的r表示字符串是“原始字符串”。它可以防止Python将字符解释为转义序列。例如,r"\n"是斜杠,后跟字母n,而不是被解释为单个换行符。我喜欢使用原始字符串作为我的正则表达式模式,即使它并不总是必要的。
  • 围绕\w*-d的括号是一个捕获组。它向正则表达式引擎指示应保存组的内容以供以后使用。
  • 序列\w表示“任何字母数字字符或下划线”。
  • *表示“前面项目的零个或多个”。 \w*一起表示“零个或多个字母数字字符或下划线”。
  • -d表示“连字符后跟字母d。

总之,(\w*-d)表示“零个或多个字母数字字符或下划线,后跟连字符和字母d。保存所有这些字符以供日后使用。”

第二个字符串描述了应该替换匹配数据的内容。 “\ 1”表示“第一个被捕获组的内容”。括号只是常规括号。总之,(\1)在此上下文中意味着“从捕获的组中获取已保存的内容,将其括在括号中,然后将其放回到字符串中”。

如果您想要匹配的字符多于字母数字和下划线,您可以将\w替换为您想要匹配的任何字符集。

>>> re.sub(r"([\w\.\[\]]*-d)", r"(\1)", "{{startingHere[zero1].my_string-d }}")
'{{(startingHere[zero1].my_string-d) }}'

如果您还想匹配以“-d()”结尾的单词,则可以将括号对与\(\)匹配,并使用?将其标记为可选。

>>> re.sub(r"([\w\.\[\]]*-d(\(\))?)", r"(\1)", "{{startingHere[zero1].my_string-d() }}")
'{{(startingHere[zero1].my_string-d()) }}'

答案 1 :(得分:0)

如果您希望包围仅在双花括号内进行,则需要以下内容:

re.sub(r'({{\s*)([^}]*-d)(\s*}})', r'\1(\2)\3', s)

打破这一点:

# the target pattern
r'({{\s*)([^}]*-d)(\s*}})'
# ^^^^^^^ capture group 1, opening {{ plus optional space
#        ^^^^^^^^^ capture group 2, non-braces plus -d
#                 ^^^^^^^ capture 3, spaces plus closing }}

替换r'\1(\2)\3'只是组装组 围绕中间的括号。

把它放在一起:

import re

def quote_string_d(s):
    return re.sub(r'({{\s*)([^}]*-d)(\s*}})', r'\1(\2)\3', s)

print(quote_string_d("this is my {{string-d}}"))
print(quote_string_d("this is my second{{ new_string-d }}"))
print(quote_string_d("this should not be quoted other_string-d "))

输出:

this is my {{(string-d)}}
this is my second{{ (new_string-d) }}
this should not be quoted other_string-d 

请注意,第三个实例没有括号,因为它不在{{ }}内。