我有一个场景,我需要使用一次调用Python的re.sub()来查找和替换字符串中的项目。如果这种约束听起来很人为,那么只要将其视为心理练习,但要知道这是我必须要处理的现实约束。
我希望匹配并替换以下任一行:
foo -some-arg -o %output %input
foo %input -other-random-arg=baz -o %output
用这个:
bar %output %input.out
文件名%input和%output可以是匹配[a-zA-Z0-9._-]+
的任何内容,但始终以%
我提出了这种替代方法,这种方法并不奏效。
r'''(?x) # Begin verbose regex
foo[ ] # foo and a space
(?=.*?-o[ ] # Lookahead for the first occurrence of -o
(?P<a>%\S+\b) # Output filename -> Group 'a'
)
(?=.*? # Lookahead from the same place as the first lookahead
# so the two filenames can match in any order.
(?!-o[ ]%\S+\b) # Do not match the output file
(?P<b>%\S+\b) # Any filename -> Group 'b'
).* # Match anything ''',
r'bar \g<b> \g<a>.out' # Replacement
我经常最终将两个文件名中的一个重复两次,如:
bar %output %output.out
有没有办法按照它们出现的顺序命名捕获两个文件名?似乎如果我可以在匹配其中一个前瞻时推进正则表达式引擎的指针,我可以做到这一点。
答案 0 :(得分:2)
由于所有参数都以破折号开头,并且由于输入和输出总是存在一次,因此您可以使用忽略该顺序的这种模式:
foo(?: -o (?P<output>\S+)| -\S+| (?P<input>\S+))+
和替换
bar \1 \2.out
注意:如果要处理包含空格的文件名(在命令行中转义),则需要将\S+
更改为(?:[^\s\\]+(?:\\.[^\s\\]*)*|[^\s\\]*(?:\\.[^\s\\]*)+)
(仅用于输入和输出)