所以,我刚刚开始理解正则表达式,我发现学习曲线相当陡峭。但是,stackoverflow在我的实验过程中非常有用。我想写一个特定的单词宏,但我还没有想出办法。我希望能够在一个文档中找到彼此10个左右的单词中的两个单词,然后将这些单词用斜体字表示,如果这些单词相隔超过10个单词或者顺序不同,我希望宏不要用斜体表示那些话。
我一直在使用以下正则表达式:
\bPanama\W+(?:\w+\W+){0,10}?Canal\b
然而,它只允许我操纵整个字符串作为一个整体,包括其间的随机单词。此外,.Replace函数只允许我用不同的字符串替换该字符串而不更改格式样式。
更有经验的人是否知道如何使这项工作?它甚至可以吗?
Sub RegText()
Dim re As regExp
Dim para As Paragraph
Dim rng As Range
Set re = New regExp
re.Pattern = "\bPanama\W+(?:\w+\W+){0,10}?Canal\b"
re.IgnoreCase = True
re.Global = True
For Each para In ActiveDocument.Paragraphs
Set rng = para.Range
rng.MoveEnd unit:=wdCharacter, Count:=-1
Text$ = rng.Text + "Modified"
rng.Text = re.Replace(rng.Text, Text$)
Next para
End Sub
好的,感谢蒂姆·威廉姆斯的帮助下面我得到了以下解决方案,它在某些方面有点笨拙并且它绝不是纯粹的正则表达式但它 完成工作。如果有人有更好的解决方案或想法如何解决这个问题,我会很高兴听到它。再一次,我的粗暴用搜索和替换功能强制改变是一个有点令人尴尬的粗糙,但至少它的工作...
Sub RegText()
Dim re As regExp
Dim para As Paragraph
Dim rng As Range
Dim txt As String
Dim allmatches As MatchCollection, m As match
Set re = New regExp
re.pattern = "\bPanama\W+(?:\w+\W+){0,13}?Canal\b"
re.IgnoreCase = True
re.Global = True
For Each para In ActiveDocument.Paragraphs
txt = para.Range.Text
'any match?
If re.Test(txt) Then
'get all matches
Set allmatches = re.Execute(txt)
'look at each match and hilight corresponding range
For Each m In allmatches
Debug.Print m.Value, m.FirstIndex, m.Length
Set rng = para.Range
rng.Collapse wdCollapseStart
rng.MoveStart wdCharacter, m.FirstIndex
rng.MoveEnd wdCharacter, m.Length
rng.Font.ColorIndex = wdOrange
Next m
End If
Next para
Selection.Find.ClearFormatting
Selection.Find.Font.ColorIndex = wdOrange
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Font.Italic = True
With Selection.Find
.Text = "Panama"
.Replacement.Text = "Panama"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Font.ColorIndex = wdOrange
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Font.Italic = True
With Selection.Find
.Text = "Canal"
.Replacement.Text = "Canal"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Font.ColorIndex = wdOrange
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Font.ColorIndex = wdBlack
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
答案 0 :(得分:6)
我还不是一个体面的Word程序员,但这可能会让你开始。
编辑:已更新为包含参数化版本。
Sub Tester()
HighlightIfClose ActiveDocument, "panama", "canal", wdBrightGreen
HighlightIfClose ActiveDocument, "red", "socks", wdRed
End Sub
Sub HighlightIfClose(doc As Document, word1 As String, _
word2 As String, clrIndex As WdColorIndex)
Dim re As RegExp
Dim para As Paragraph
Dim rng As Range
Dim txt As String
Dim allmatches As MatchCollection, m As match
Set re = New RegExp
re.Pattern = "\b" & word1 & "\W+(?:\w+\W+){0,10}?" _
& word2 & "\b"
re.IgnoreCase = True
re.Global = True
For Each para In ActiveDocument.Paragraphs
txt = para.Range.Text
'any match?
If re.Test(txt) Then
'get all matches
Set allmatches = re.Execute(txt)
'look at each match and hilight corresponding range
For Each m In allmatches
Debug.Print m.Value, m.FirstIndex, m.Length
Set rng = para.Range
rng.Collapse wdCollapseStart
rng.MoveStart wdCharacter, m.FirstIndex
rng.MoveEnd wdCharacter, Len(word1)
rng.HighlightColorIndex = clrIndex
Set rng = para.Range
rng.Collapse wdCollapseStart
rng.MoveStart wdCharacter, m.FirstIndex + (m.Length - Len(word2))
rng.MoveEnd wdCharacter, Len(word2)
rng.HighlightColorIndex = clrIndex
Next m
End If
Next para
End Sub
答案 1 :(得分:0)
如果你一次只做两个单词,这对我有用,跟着你的练习线。
foo([a-zA-Z0-9]+? ){0,10}bar
<强>说明:强>
将获取单词1(foo
),然后匹配任何字母数字字符([a-zA-Z0-9]+?
),后跟空格(),10次(
{0,10}
) ,然后单词2(bar
)。
此不包括完整停靠(不知道您是否需要它们),但是如果您只想在.
之后添加0-9
正则表达式。
所以你的(伪代码)语法将类似于:
$matches = preg_match_all(); // Your function to get regex matches in an array
foreach (those matches) {
replace(KEY_WORD, <i>KEY_WORD</i>);
}
希望它有所帮助。下面的测试,突出了它匹配的内容。
<强>曾为:强>
foo this that bar
等等
foo economic order war bar
无效
foo经济秩序。战争吧
全球foo秩序已经存在了几个世纪,在这段时间里,人们已经发展出处理农业和酒吧等情况的不同和错综复杂的贸易关系