如何使用正则表达式识别重复的字符?

时间:2016-03-31 16:08:53

标签: regex sed

这个问题涉及正则表达式拼图。我有一个带有重复字符的单词列表,例如

stubbornness
raccoon
cooccurred
successful

请注意,每个条款都有两组重复的字母,例如" bb","固执"。我已经编写了我的脚本(在ruby中),并且我能够在代码循环中使用每个字符的迭代来解决我的任务。

但是,这个令人费解的任务引起了我的注意......我想知道是否可以使用正则表达式来完成它?我已经查阅了正则表达式教程和其他StackOverflow问题,但我无法弄清楚如何报告欺骗角色。这是所需的输出:

bb stubbornness
cc raccoon
oo cooccurred
cc successful

前面有第一组重复的字母。我曾尝试编写自己的正则表达式(在MacOS上使用sed;在Ubuntu而不是-E上使用-r):

sed -E 's#(.*?)(.)\2(.*)#\2\2 \1\2\2\3#g'

但是它有一个无效的重复操作符操作数。有任何想法吗?请注意,重复的字符可以是字符串中的任何位置。

5 个答案:

答案 0 :(得分:2)

试试这个RegEx:

(.*?)((\w)\3)(.*)

代替:

\2 \1\2\4

Live Demo on Regex101

感谢 @Kent ,他告诉我sed不支持懒惰.*?,我想出了这个新的RegEx:

(
(?!(\w)\2)       # DO NOT Match if there are double letters
.                # Data before dobule letters
)*
((\w)\4)         # Double Letter
(.*)             # Data after letters

# SHORTER REGEX (1 LINE)
((?!(\w)\2).)*((\w)\4)(.*)

代替:

\3 \0

Live Demo on Regex101

答案 1 :(得分:1)

如果你有 gnu sed ,这个单行(在rev的帮助下,是unix-util的成员)可以工作:

 sed -r 's/.*(.)\1.*/echo "\1\1 $(echo \0|rev)"/ge' <(rev file)

试验:

kent$  cat f
stubbornness
raccoon
cooccurred
successful

kent$  sed -r 's/.*(.)\1.*/echo "\1\1 $(echo \0|rev)"/ge'  <(rev f)
bb stubbornness
cc raccoon
oo cooccurred
cc successful

答案 2 :(得分:0)

有趣。这是一个不完美的解决方案。你的话总是有2套重复的字母吗?如果是这样,这将报告倒数第二个,在您的情况下是第一个:

sed 's#\(.*\)\(.\)\2\(.*\)\(.\)\4#\2\2 &#'

注意,这里没有扩展的正则表达式(sed没有-r / -E)。但抱歉,我不知道如何检测第一次出现。 \ 4强制\ 2检测倒数第二个。如果你省略这个:\(.*\)\(.\)\4那么它只报告最后一对重复的字母。

答案 3 :(得分:0)

如何使用-r的rev和GNU sed?

$ rev file | sed -r 's/(.*((.)\3).*)/& \2/' | rev
bb stubbornness
cc raccoon
oo cooccurred
cc successful

FWIW在这里我是如何使用标准的UNIX工具而不是Ruby来解决问题的,而不是试图用sed中的正则表达式来解决它:

$ awk -v FS= '{p=""; for (i=1;i<=NF;i++) { if ($i==p) {print p $i, $0; next} p=$i } }' file
bb stubbornness
cc raccoon
oo cooccurred
cc successful

有些awks在给定空FS的情况下不会将一行划分为字符,因此这是可在所有awks中使用的可移植版本:

$ awk '{p=""; for (i=1;i<=length($0);i++) { c=substr($0,i,1); if (c==p) {print p c, $0; next} p=c } }' file
bb stubbornness
cc raccoon
oo cooccurred
cc successful

答案 4 :(得分:0)

Perl是你的朋友:

> perl -ne 'print @_[0,0], " $_" if (@_ = /(.)\1/g) > 1' < words.txt
bb stubbornness
cc raccoon
oo cooccurred
cc successful
> 

这不会为任何不包含至少两组双字母的输入字打印任何内容。列出一个单词中找到的所有双打并不是更多的工作。并轻松调整三组:

> perl -ne 'print @_[0,0], " $_" if (@_ = /(.)\1/g) > 2' < wordlist.txt
ss Mississippi
ss Mississippian
ll Tallahassee
nn Tennessee
dd addressee
tt bitterroot
oo bookkeep
mm committee

如果您只搜索至少一对双字母,那么问题会变得更简单:

perl -ne 'print "$& $_" if /(.)\1/' < wordlist.txt | tail
ll yellowish
ll you'll
tt ytterbium
tt yttrium
cc yucca
gg zigzagging
oo zoo
oo zoology
oo zoom
cc zucchini