正则表达式匹配所有的单词对。

6

我正在尝试从一段文本中获取所有的词语对。

我有以下正则表达式(\w+) +(\w+),我在没有标点符号的文本上运行它。我的问题是这种方法不能考虑到所有可能的词语对。

$ echo "hello dear world" | grep -Eoi "(\w+) +(\w+)"
hello dear 

我希望你能提供以下服务

$ echo "hello dear world" | grep -Eoi [some expression]
hello dear 
dear world
5个回答

5

传统的 grep 不会返回捕获组。

你可以考虑使用带有向前查看和两个捕获组的 pcregrep

echo "hello dear world" | pcregrep -o1 -o2 '(\w+)(?=(\h+\w+))'

hello dear
dear world

如果您没有 pcregrep,那么您可以使用这个简单的 awk

awk '{for (i=1; i<NF; ++i) print $i OFS $(i+1)}' <<< "hello dear world"

hello dear
dear world

4

根据您提供的示例,这里介绍一种使用 awk 程序完成此操作的方法 (任何版本的 awk 都可以正常工作)。

echo "hello dear world" | awk '{for(i=2;i<NF;i++){$i=$i ORS $i}} 1'

Explanation: 简单的解释是,通过echo命令打印值并将其作为标准输入发送到awk程序。然后在awk程序中,遍历字段(仅偶数字段),将这些字段重新分配为其自身的值,后跟换行符和它们自己的值,然后打印编辑/未编辑的行。


4

使用GNU awk进行多字符RS和\s简写:

$ echo "hello dear world" | awk -v RS='\\s+' 'NR>1{print p OFS $0} {p=$0}'
hello dear
dear world

1
Perl允许使用lookaround,因此您可以使用一种常见的技术,在正向前瞻中使用捕获组来匹配重叠文本:
perl -lne 'print "$1" while /\b(?=(\w+\s+\w+))/g' file

查看一个在线演示

s="hello dear world"
perl -lne 'print "$1" while /\b(?=(\w+\s+\w+))/g' <<< "$s"

输出:

hello dear
dear world

查看正则表达式演示详情

  • \b - 单词边界
  • (?=(\w+\s+\w+)) - 正向先行断言,要求当前位置的右侧立即出现:
    • (\w+\s+\w+) - 捕获组 1:
      • \w+ - 一个或多个单词字符
      • \s+ - 一个或多个空格字符
      • \w+ - 一个或多个单词字符

1

使用ripgrep

% echo "hello dear world" | rg '(\w+)\s(\w+)\s(\w+)' -r "$(printf '$1 $2\n$2 $3')"
hello dear
dear world

要基于3个单词做所有2个单词的组合,可以使用crunch命令进行组合,例如:

% echo "hello dear world" | rg -o '(\w+)\s(\w+)\s(\w+)' -r "$(crunch 5 5 + + 123 -t '$% $%' 2>/dev/null)"
hello hello
hello dear
hello world
dear hello
dear dear
dear world
world hello
world dear
world world

关于重叠匹配的更多信息,请参见:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接