我正在尝试从一段文本中获取所有的词语对。
我有以下正则表达式(\w+) +(\w+)
,我在没有标点符号的文本上运行它。我的问题是这种方法不能考虑到所有可能的词语对。
$ echo "hello dear world" | grep -Eoi "(\w+) +(\w+)"
hello dear
我希望你能提供以下服务
$ echo "hello dear world" | grep -Eoi [some expression]
hello dear
dear world
传统的 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
根据您提供的示例,这里介绍一种使用 awk
程序完成此操作的方法 (任何版本的 awk
都可以正常工作)。
echo "hello dear world" | awk '{for(i=2;i<NF;i++){$i=$i ORS $i}} 1'
Explanation: 简单的解释是,通过echo
命令打印值并将其作为标准输入发送到awk
程序。然后在awk
程序中,遍历字段(仅偶数字段),将这些字段重新分配为其自身的值,后跟换行符和它们自己的值,然后打印编辑/未编辑的行。
使用GNU awk进行多字符RS和\s
简写:
$ echo "hello dear world" | awk -v RS='\\s+' 'NR>1{print p OFS $0} {p=$0}'
hello dear
dear world
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+
- 一个或多个单词字符使用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
关于重叠匹配的更多信息,请参见: