正则表达式从字符串中提取前3个单词

时间:2014-01-25 02:46:35

标签: regex

我正在尝试替换除String中前三个单词之外的所有单词(使用textpad)。

Ex值: This is the string for testing.

我想从上面的字符串中提取3个单词: This is the 并删除所有其他单词。

我发现正则表达式匹配3个单词 (\w+\s+){3} 但是我需要匹配除前3个单词之外的所有其他单词并删除其他单词。有人可以帮我吗?

3 个答案:

答案 0 :(得分:5)

究竟如何取决于口味,但要消除除前三个词之外的所有内容,您可以使用:

^((?:\S+\s+){2}\S+).*

将前三个单词捕获到捕获组1以及字符串的其余部分。对于替换字符串,您使用对捕获组1的引用。在C#中,它可能看起来像:

resultString = Regex.Replace(subjectString, @"^((?:\S+\s+){2}\S+).*", "${1}", RegexOptions.Multiline);

答案 1 :(得分:1)

编辑:为每个正则表达式添加了行首锚,并添加了TextPad特定标志。

如果你想消除前三个单词,并捕获其余单词,

^(?:\w+\s+){3}([^\n\r]+)$

?:将前三个单词更改为非捕获组,并捕获其后的所有内容。

这是你要找的吗?我对你的问题或你的目标并不完全清楚。

正如所建议的,这是相反的。仅捕获前三个单词,然后丢弃其余单词:

^(\w+\s+){3}(?:[^\n\r]+)$

只需将?:从第一个分组移动到第二个分组。

至于替换捕获的组,您希望它被替换为什么?要单独替换每个单词,您必须单独捕获每个单词:

^(\w+)\s+(\w+)\s+(\w+)\s+(?:[^\n\r]+)$

然后,例如,您可以用首字母大写替换每个字母:

替换为:\u$1 \u$2 \u$3

结果为This Is The

在TextPad中,替换中的小写\u表示仅更改下一个字母。大写\U更改后面的所有内容(直到下一个大写标记)。

试一试:

http://fiddle.re/f3hgv

(按[Java]或任何最相关的语言。请注意,RegexPlanet不支持\ u。)

答案 2 :(得分:1)

来自一个重复的问题,我将发布适用于“传统”正则表达式实现的解决方案,该解决方案不支持Perl扩展\s\W等。甚至不熟悉的新手事实上,建议使用正则表达式的不同方言(aka flavors)来阅读例如Why are there so many different regular expression dialects?

如果您有POSIX类支持,则可以[[:alpha:]]使用\w[^[:alpha:]]使用\W[[:space:]]使用\s等但是如果我们假设空格总是一个空格而你想要在空格之间提取前三个标记,那么你甚至不需要它。

[^ ]+[ ]+[^ ]+[ ]+[^ ]+

匹配由空格运行分隔的三个标记。 (我将空格放在括号中,以便在标记分隔符集中包含除了单个常规ASCII空间之外的其他字符,并且易于扩展。例如,如果正则表达式方言接受\t对于标签,或者您可以在其位置粘贴常规标签,您可以将其扩展到

[^ \t]+[ \t]+[^ \t]+[ \t]+[^ \t]+

在大多数shell中,您可以使用 ctrl + v tab 键入文字选项卡,即在其前面加上转义码,即经常通过按住 ctrl 键并输入 v 来输入。)

要实际使用它,您可能想要

grep -Eo '[^ ]+[ ]+[^ ]+[ ]+[^ ]+' file

其中单引号是保护正则表达式从shell中所必需的(双引号也可以在这里工作,但是更弱,或者反映正则表达式中对shell作为元字符有意义的每个字符)或者可能< / p>

sed -r 's/([^ ]+[ ]+[^ ]+[ ]+[^ ]+).*/\1/' file

用仅捕获的表达式替换每一行(括号创建一个捕获组,您可以在\1 s命令的替换部分中使用sed引用该组。 )。 -r选项选择略微更具特色的正则表达式方言,而不是传统的sed。如果您的sed没有,请尝试-E,或在每个括号和加号前加一个反斜杠。

由于正则表达式的工作方式, first 三是很容易的,因为正则表达式引擎总会在一行上返回第一个可能的匹配。如果你想要从 second,开始的三个标记,你必须放入一个跳过表达式。调整上面的sed脚本,即

sed -r 's/[^ ]+[ ]+([^ ]+[ ]+[^ ]+[ ]+[^ ]+).*/\1/'

你会注意到我在捕获之前如何放入令牌+非令牌组。 (对于grep -o,这是不可能的,除非您有grep -P,在这种情况下,无论如何都可以使用完整的Perl扩展。)

如果你的正则表达式方言支持 {m,n} 重复,你当然可以重构正则表达式来使用它。如果你需要大量的重复,它肯定更具可读性和可维护性。只需确保在分解反向引用顺序的地方不添加括号(第一个左括号创建第一个组\1,第二个\2等。)

sed -r 's/([^ ]+([ ]+[^ ]+){2}).*/\1/' file

注意第二个括号组是如何指定{2}重复范围所必需的(我们希望重复的不仅仅是左大括号之前的单个字符)。 OP的尝试有一个错误,其中重复被指定在最后一个括号之外;那么,后面的引用\1(或者你在方言中调用的任何东西 - TextMate似乎使用$1,就像Perl一样)将引用捕获括号的最后一个匹配,因为重复是不是捕获的一部分,不在捕获括号内。