我有这个测试字符串
'{"hello": "my-friend", "hello2": "my friend", "field": True, "nxt":"hello:what", "nxt2": Mystr}'
在这种情况下,我只想匹配
Mystr
和 True
。所以我想匹配未引用的值。
我的第一个方法:
":(?: )?(.*?)?[\,\}]
然后我遇到了这个问题,我尝试采用我的场景。不幸的是,这一点失败了。
"[^"\\]*(?:\\.[^"\\]*)*"(*SKIP)(*F)|(?<!\S)([^"\s]+)(?!\S)
我也想了解到底是怎么回事。我的方法对我来说很清楚。我复制粘贴的那个还不是很远。
稍后我将使用
re
在 python 脚本中使用正则表达式。
后续编辑21.01.
我的实际目标是到目前为止修复这个测试字符串,使其成为有效的 json。固定字符串应被
json.loads()
接受。所以我想将示例修改为
'{"hello": "my-friend", "hello2": "my friend", "field": "True", "nxt":"hello:what", "nxt2": "Mystr"}'
您的输入字符串似乎是有效的 Python 代码。由于您正在寻找裸名称,因此最好使用 Python 的 tokenizer 来查找它们:
from token import NAME
from tokenize import generate_tokens
s = '{"hello": "my-friend", "hello2": "my friend", "field": True, "nxt":"hello:what", "nxt2": Mystr}'
print([name for typ, name, *_ in generate_tokens(iter([s]).__next__) if typ == NAME])
输出:
['True', 'Mystr']
演示这里
blhsing的答案是首选方式。但如果你真的需要它成为一个与
re
一起使用的正则表达式,那么这个应该可以完成这项工作:
[^\w"]*(?:"(?:\\.|[^"])*"[^\w"]*)*([^\W\d]\w*)
与
findall
一起使用:
s = '''[None, {"hello": "my-friend", "hello2": "my friend is here", "field": True,
"nxt":"hello:what", "nxt2": Mystr, "list": [item, _item2,µ ,88, -9 ]}]'''
words = re.findall(r'[^\w"]*(?:"(?:\\.|[^"])*"[^\w"]*)*([^\W\d]\w*)', s)
print(words) # ['None', 'True', 'Mystr', 'item', '_item2', 'µ']
(注意:我在输入中添加了更多案例)
如果目标是调整输入字符串,在这些术语周围添加引号,则使用类似的正则表达式与
re.sub
:
s = re.sub(r'([^\w"]*(?:"(?:\\.|[^"])*"[^\w"]*)*)([^\W\d]\w*)', r'\1"\2"', s)
由于您只想匹配未引用的单词(
Mystr
和True
),这里有一个简单的正则表达式:
(?<!["])\b[A-Za-z]+\b(?!["])
在Python中:
import re
pattern = r'(?<!["])\b[A-Za-z]+\b(?!["])'
text = '{"hello": "my-friend", "hello2": "my friend", "field": True, "nxt":"hello:what", "nxt2": Mystr}'
data = re.findall(pattern, text)
print(data)
输出:
['True', 'Mystr']
注释:
(?<!["])
:确保单词前面没有紧接着双引号 (")。(?!["])
:确保单词后面不会紧跟着双引号 (")。[A-Za-z]+
:匹配一个或多个字母字符。\b
:断言单词边界以确保匹配在非单词字符或边界处开始或结束。与双引号类似,您只需将单引号或任何其他字符添加到边界条件即可轻松避免使用单引号或任何其他字符。
您可以尝试匹配所有非分隔符,但请参阅 json.org 了解详细信息。
([\s{}\[\],:]*(?:"(?:\\.|[^"])*"[\s{}\[\],:]*)*)([^{}\[\],:"]+)