如何使用shell变量使Grep更少贪婪?

时间:2015-05-06 00:50:46

标签: regex bash shell grep regex-greedy

我一直在用我发现的特定问题来提高我的grep技能。基本上就是这样的。我有一个本地文件,其中包含字典中的单词。用户将传入一个单词,脚本将找到可以使用该单词中的字母创建的所有单词。问题是,单词长度必须至少为4个字符,并且您只能使用与用户传入的字母一样多的字母。因此,如果我传入了像" College" clee和cell是可接受的单词,但不是像cocco这样的单词,因为它包含来自单词的字母,但大学只有1 o和1 c。到目前为止,这是我的正则表达式。

egrep -i "^[("$text")]{4,}$" /usr/dict/words   

这将找到包含这些字母的字符串,这些字母长度至少为四个字符,但grep正在贪婪并且比变量中的字符抓取更多字符。我如何指定仅使用变量中的字符数量?我已经被困在这几天了,现在无济于事。感谢您的帮助和时间社区!

1 个答案:

答案 0 :(得分:0)

为了扩展@chepner在评论中所说的内容,正则表达式不会测试范围内的确切字符数。换句话说,[ee]与2 e不匹配,只有在有e时才会匹配,因此[ee][e]的冗余。正则表达式通常匹配一个或多个匹配表达式[e]+将匹配至少1 e直到字符串的缓冲区大小。要匹配特定数量的e,您必须事先知道[e]{2,5}之类的内容至少匹配2 {但不超过5 {{1} e }}'第

即使您设置预处理器来计算输入中重复的字母数,您也很难将正则表达式与您认为匹配的方式相匹配。要使用" college"的例子,预处理看起来像c = 1,o = 1,l = 2,e = 2,g = 1。如果你把它放在正则表达式中,就像你有^ c?o?l {0,2} e {0,2} g?$`[注意a"?"在这种情况下,{0,1}]的简写甚至不匹配"大学"因为匹配将是位置匹配" colleg"," colleeg"," colleg"等。

要验证字符串的长度,您只能验证至少有[]范围内的字母。您可能希望将其更改为grep "^.{4,}$"以检查整个长度是否至少为4个字符。

如果您不仅限于使用grep,但仅限于bash,您可以使用以下脚本来解决您的问题:

read input
cat /usr/dictwords | while read line
do
  if $(echo $line | grep "^.\{4,\}\$" >> /dev/null)
  then
    testVal=$line
    for i in $(echo $input | sed -e 's/\(.\)/\1 /g')
      testVal=$(echo "$testVal" | sed -e "s/$i/_/i")
    done
  fi
  if $(echo $testVal | grep "^_\+$" >> /dev/null)
  then
    echo $line
  fi
done