我有一份文件,其中包含各种格式的数字,法语,英语,自定义格式。
我想要一个只能以法语格式捕获数字的正则表达式。
这是我要捕获的完整数字列表(d
表示数字,小数点分隔符为逗号,
,千位分隔符为空格)
d,d d,dd d,ddd
dd,d dd,dd dd,ddd
ddd,d ddd,dd ddd,ddd
d ddd,d d ddd,dd d ddd,ddd
dd ddd,d dd ddd,dd dd ddd,ddd
ddd ddd,d ddd ddd,dd ddd ddd,ddd
d ddd ddd,d...
dd ddd ddd,d...
ddd ddd ddd,d...
这是我的正则表达式
(\d{1,3}\s(\d{3}\s)*\d{3}(\,\d{1,3})?|\d{1,3}\,\d{1,3})
捕获上面的法语格式,因此我走在正确的轨道上,但也有d,ddd.dd
之类的数字(因为它捕获d,ddd
)或d,ddd,ddd
(因为它捕获d,ddd
})。
我应该在正则表达式中添加什么内容?
我的VBA代码:
Sub ChangeNumberFromFRformatToENformat()
Dim SectionText As String
Dim RegEx As Object, RegC As Object, RegM As Object
Dim i As Integer
Set RegEx = CreateObject("vbscript.regexp")
With RegEx
.Global = True
.MultiLine = False
.Pattern = "(\d{1,3}\s(\d{3}\s)*\d{3}(\,\d{1,3})?|\d{1,3}\,\d{1,3})"
' regular expression used for the macro to recognise FR formated numners
End With
For i = 1 To ActiveDocument.Sections.Count()
SectionText = ActiveDocument.Sections(i).Range.Text
If RegEx.test(SectionText) Then
Set RegC = RegEx.Execute(SectionText)
' RegC regular expresion matches collection, holding french format numbers
For Each RegM In RegC
Call ChangeThousandAndDecimalSeparator(RegM.Value)
Next 'For Each RegM In RegC
Set RegC = Nothing
Set RegM = Nothing
End If
Next 'For i = 6 To ActiveDocument.Sections.Count()
Set RegEx = Nothing
End Sub
用户stema,给了我一个很好的解决方案。正则表达式应该是:
; | \ d {1,3}(小于= ^ \ S')(?:\ S \ d {3})*?(?:\,\ d {1,3})( ?= \ S | $)
但是VBA抱怨正则表达式没有未转义的字符。我在(?:\ d {3})之间找到了一个(?:\ d {3}),这是一个空白字符,所以我可以用\ s替换它。我认为第二个(?:,\ d {1,3})介于?:和\ d之间,逗号字符,如果我转义它将是\,。
所以正则表达式现在是(?< = ^ | \ s)\ d {1,3}(?:\ s \ d {3})*(?:\,\ d {1,3}) ?(?= \ s | $)并且它在RegExr中工作正常但我的VBA代码不接受它。
邮政新线: 我刚刚发现VBA不同意正则表达式的这一序列?< = ^
答案 0 :(得分:2)
这个怎么样?
\b\d{1,3}(?: \d{3})*(?:,\d{1,3})?\b
\b
是字边界
首先(\d{1,3}
)匹配1到3位数,然后可以有0个或更多个前导空格组,后跟3个数字((?: \d{3})*
),最后可以有一个可选的分数部分((?:,\d{1,3})?
)
修改强>
如果你想避免1,111.1
,那么\b
锚点对你不利。试试这个:
(?<=^|\s)\d{1,3}(?: \d{3})*(?:,\d{1,3})?(?=\s|$)
这个正则表达式现在需要一个空格或前面的字符串的开头,以及要匹配的数字之后的空格或字符串的结尾。
编辑2:
由于不支持外观,您可以更改为
(?:^|\s)\d{1,3}(?: \d{3})*(?:,\d{1,3})?(?=\s|$)
这在字符串的开头没有任何变化,但是如果数字以前导空格开头,则现在包含在匹配中。如果匹配的结果首先用于某些东西,则必须剥离前导空格(我非常确定VBA确实有一个方法(尝试trim()
))。
答案 1 :(得分:0)
如果您逐行阅读,可以考虑在正则表达式中添加锚点^
和$
),这样您最终会得到类似的结果:
^(\d{1,3}\s(\d{3}\s)*\d{3}(\,\d{1,3})?|\d{1,3}\,\d{1,3})$
这指示RegEx引擎从行的开头直到最后开始匹配。