Regex Word宏,找到彼此相距一定范围内的两个单词,然后将这些单词斜体化?
所以,我刚刚开始理解正则表达式,我发现学习曲线相当陡峭。然而,stackoverflow在我的实验过程中非常有用。有一个特定的单词宏,我想写,但我还没有找到一个方法来做到这一点。我希望能够在文档中找到10个左右单词中的两个单词,然后将这些单词斜体化,如果单词之间的间隔超过10个单词或顺序不同,我希望宏不要将这些单词斜体化 我一直在使用以下正则表达式:Regex Word宏,找到彼此相距一定范围内的两个单词,然后将这些单词斜体化?,regex,vba,search,ms-word,Regex,Vba,Search,Ms Word,所以,我刚刚开始理解正则表达式,我发现学习曲线相当陡峭。然而,stackoverflow在我的实验过程中非常有用。有一个特定的单词宏,我想写,但我还没有找到一个方法来做到这一点。我希望能够在文档中找到10个左右单词中的两个单词,然后将这些单词斜体化,如果单词之间的间隔超过10个单词或顺序不同,我希望宏不要将这些单词斜体化 我一直在使用以下正则表达式: \bPanama\W+(?:\w+\W+){0,10}?Canal\b 但是,它只允许我将整个字符串作为一个整体进行操作,包括中间的随机单词。另
\bPanama\W+(?:\w+\W+){0,10}?Canal\b
但是,它只允许我将整个字符串作为一个整体进行操作,包括中间的随机单词。另外,.Replace函数只允许我用不同的字符串替换该字符串,而不允许更改格式样式
有没有经验更丰富的人对如何使这项工作有想法?甚至可以这样做吗
编辑:这是我到目前为止的资料。我有两个问题。首先,我不知道如何仅从匹配的正则表达式中选择单词“Panama”和“Canal”,并仅替换这些单词(而不是中间单词)。第二,我只是不知道如何替换一个与不同格式匹配的Regexp,只是一个不同的文本字符串——这可能是因为我不熟悉word宏
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
好的,感谢下面Tim Williams的帮助,我得到了下面的解决方案,它在某些方面有点笨拙,它绝对不是纯regexp,但它确实完成了任务。如果有人有更好的解决方案或想法来解决这个问题,我会很高兴听到。再一次,我用“搜索和替换”功能强制更改有点让人难堪,但至少它是有效的
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
如果你一次只做两个单词,这对我来说很有效,遵循你的练习路线
foo([a-zA-Z0-9]+? ){0,10}bar
说明:
将抓取单词1(foo
),然后匹配任何字母数字字符的单词([a-zA-Z0-9]+?
),后跟一个空格(
),10次({0,10}
),然后匹配单词2(条)
此不包含句号(不知道是否需要),但如果您只想在正则表达式中的0-9
之后添加
因此,您的(伪代码)语法类似于:
$matches=preg_match_all();//获取数组中正则表达式匹配项的函数
(那些比赛){
替换(关键字,关键字);
}
希望能有帮助。下面的测试突出显示了它匹配的内容
已工作:
这个条上的foo这个条
blah
foo经济秩序战争栏
不起作用
福经济秩序。战争酒吧
全球食品秩序已经存在了几个世纪,在这段时间里,人们已经形成了不同而复杂的贸易关系,处理诸如农业和酒吧之类的情况。我离成为一个像样的文字程序员还有很长的路要走,但这可能会让你开始
编辑:更新为包含参数化版本
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
Match对象有一个Index属性,它告诉您匹配发生在文本中的什么位置。您可以使用它来处理特定范围,以更改其格式。如果你更新你的问题以显示你现有的代码,有人可能会加入建议的更改。显示你正在运行正则表达式的单词列表。是单词多于10个单词
还是单词多于10个字母
或者句子多于10个单词
?@TimWilliams我会查看匹配属性并无论我有机会发布什么,我从来没有真正做过比基本VBA更多的事情,所以我不确定我能从中得到多少。@jared我没有一个具体的单词列表,而是一堆新闻文章,我希望能够将可能不相邻的特定单词对斜体化,例如“global”在单词“war”的10个单词中,也许我遗漏了一些东西,我的问题是我只能更改整个正则表达式匹配(即“foo”和“bar”之间的所有单词也都被更改)。我不知道如何进行匹配,然后只更改单词“foo”和“bar”,而不影响匹配文本中的任何其他单词。第二个问题更多的是由于我没有很好的GoogleFu或者不熟悉VBA宏,我不知道如何更改匹配的Regexp格式,只知道如何替换内容。我用目前正在使用的宏更新了我的问题。这在查找文本和更改其格式方面做得很好,我遇到的真正问题是,我所做的所有宏只能更改整个短语(而不仅仅是单词“巴拿马”和“运河”)。例如,上面的宏突出显示了“巴拿马运河项目”中的所有单词,而不是该短语的最后一个单词,它可能只是我试图做的是不可能的…不是不可能的:我只是没有为你做整件事:-)你知道第一个单词将是巴拿马,所以请点亮它(你知道它从哪里开始,它的长度).最后一个词是canal,所以请把它也亮起来。在这一点上只有基本的数学…是的,我实际上想出了一个解决方法-它不是很优雅,但我会把它贴在我原来的第一个问题中,我一直都在用它。谢谢你的帮助,这正是我想要的。用我的解决方案更新了我的帖子这似乎一直有效,但也很难看,然而这是我能想到的唯一可行的方法,可以不费吹灰之力地改变宏观中的词汇(就像我在寻找尼采和认识论,而不是巴拿马和运河)。非常感谢
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