【问题标题】:Grep filtering of the dictionary字典的grep过滤
【发布时间】:2014-11-06 21:29:12
【问题描述】:

我很难掌握在我所在的课程中使用 grep 的方法,希望有人可以帮助指导我完成这项作业。作业如下。

使用 grep 打印 linux 字典中所有 5 个字母的小写单词,其中单个字母重复一次(aabbe 或 ababe 无效,因为 a 和 b 都在单词中两次)。旁边打印重复的字母,然后按字母升序购买非重复的字母。

老师指出,我们将需要使用几 (6) 条 grep 语句(将结果传送到下一个 grep)和 sed 语句(字符串编辑器)来重新格式化最终的单词集,然后将它们传送到读取循环中在这里你撕开三个非重复的字母并对它们进行排序。

样本输出:
退后一步
在 bft 后面
贬低贝斯
abash a bhs
吓坏了
减少赌注

除了打印 5 个字符的单词之外,我还没有弄清楚如何做,

grep "^.....$" /usr/share/dict/words |

【问题讨论】:

标签: linux bash sed grep


【解决方案1】:

没有彻底检查,但这可能有效

tr '[:upper:]' '[:lower:]' | egrep -x '[a-z]{5}' | sed -r 's/^(.*)(.)(.*)\2(.*)$/\2 \1\3\4/' | grep " " | egrep -v "(.).*\1"

但是按照你的方式去做,因为有人可能会在这里看到它。

【讨论】:

    【解决方案2】:

    一站式服务

    sed -n '
    # filter 5 letter word
    /[a-zA-Z]\{5\}/ {
    
    # lower letters
          y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxya/
    
    # filter non single double letter
          /\(.\).*\1/ !b
          /\(.\).*\(.\).*\1.*\1/ b
          /\(.\).*\(.\).*\1.*\2/ b
          /\(.\).*\(.\).*\2.*\1/ b
    
    # extract peer and single
          s/\(.\)*\(.\)\(.*\)\2\(.*\)/a & \2:\1\3\4/
    # sort singles
    :sort
          s/:\([^a]*\)a\(.*\)$/:\1\2a/
          y/abcdefghijklmnopqrstuvwxyz/zabcdefghijklmnopqrstuvwxy/
          /^a/ !b sort
    
    # clean and print
          s/..//
          s/:/ /p
          }' YourFile
    

    posix sed 所以--posix 在 GNU sed 上

    【讨论】:

      【解决方案3】:

      显然,第一点是使用grep 将其归结为仅具有单个重复的单词。我将为您提供一些有关如何做到这一点的线索。

      关键是使用反向引用,它允许您指定与先前表达式匹配的内容应该再次出现。所以如果你写

      grep -E "^(.)...\1...\1$"
      

      然后你会得到所有开头字母重新出现在第五和第九位的单词。括号的重点是让您稍后可以参考与括号中的内容匹配的任何内容;您可以使用 \1 来执行此操作(以匹配第一批括号中的内容)。

      你想说单词中的任何地方都应该有重复,这稍微复杂一些,但不多。您需要括号中的字符,然后是任意数量的字符,然后是重复的字符(未指定 ^$)。

      这也将包括有两个或多个重复项,因此下一阶段是将它们过滤掉。您可以通过grep -v 调用来做到这一点。获得至少有一个重复的 5 个字符的单词列表后,通过 grep -v 调用将它们删除,该调用会删除包含两个(或更多)重复的任何内容。这将有一个 (.),并且另一个(.),一个\1,和一个\2,它们可能以几种不同的顺序出现。

      您还需要删除包含 (.)\1 和另一个 \1 的任何内容,因为这将包含三个出现的字母。

      无论如何,这应该足以让您入门。

      【讨论】:

      【解决方案4】:

      您的下一步应该是找到包含重复字母的 5 个字母单词。为此,您将需要使用反向引用。示例:

      grep "[a-z]*\([a-z]\)[a-z]*\$1[a-z]*"

      $1 获取第一个带括号的组的内容,并希望再次匹配该组。在这种情况下,它匹配单个字母。有关此功能的更多说明,请参阅:http://www.thegeekstuff.com/2011/01/advanced-regular-expressions-in-grep-command-with-10-examples--part-ii/

      接下来,您需要过滤掉某个字母重复 3 次或单词重复 2 个字母的情况。您将需要使用相同类型的反向引用技巧,但您可以使用 grep -v 过滤结果。

      sed 可用于最终显示。 Grep 只会让您构建要考虑的正确行。

      【讨论】:

      • 我目前有这个,但它没有提供输出
        grep "^.....$" /usr/share/dict/words | grep "[a-z][a-z][a-z][a-z][a-z]" | grep "[a-z]*([a-z])[a-z]*\$1[a-z]*" 
      • 这个答案有很多问题。链接已失效。反向引用不使用$。而且您不需要在开头和结尾使用[a-z]*。如果你使用-E,那么语法就会被简化。
      【解决方案5】:

      请注意,字典包含大写字母和非字母字符,以及南欧使用的奇怪字符。说“è”。

      如果你想区分“A”和“a”,它是自动的,另一方面,如果“A”和“a”是同一个字母,在所有grep调用中你必须使用-i选项, 指示grep 忽略大小写。

      接下来,您总是希望传递-E 选项,以避免您想要传递给grep 的正则表达式中所谓的backslashitis gravis

      此外,如果您想排除输出中匹配正则表达式的行,正确的选项是-v

      最终,如果您想为单个 grep 调用指定许多不同的正则表达式,这就是方式(顺便说一句,只是一个示例)

      grep -E -i -v -e 'regexp_1' -e 'regexp_2' ... -e 'regexp_n'
      

      预赛已经结束了,让我们期待,以chiastic-security的答案作为参考了解程序

      1. 只有这些可能在 5 个字符的字符串中找到重复项

        (.)\1
        (.).\1
        (.)..\1
        (.)...\1
        

        grep -E -i -e 'regexp_1' ...

      2. 现在你有了所有的双打,但这并不排除由以下模式识别的三元组等(编辑添加了一些额外的匹配三元组模式)

        (.)\1\1
        (.).\1\1
        (.)\1.\1
        (.)..\1\1
        (.).\1.\1
        (.)\1\1\1
        (.).\1\1\1
        (.)\1\1\1\1\
        

        你想排除这些模式,所以grep -E -i -v -e 'regexp_1' ...

      3. 在他的观点上,你有一个单词列表,其中至少有几个相同的字符,没有三元组等,你想去掉双打,这些是匹配双打的正则表达式

        (.)(.)\1\2
        (.)(.)\2\1
        (.).(.)\1\2
        (.).(.)\2\1
        (.)(.).\1\2
        (.)(.).\2\1
        (.)(.)\1.\2
        (.)(.)\2.\1
        

        并且你想排除这些模式的行,所以它的grep -E -i -v ...

      最后一个提示,在你的工作目录中复制几百行字典,head -n 3000 /usr/share/dict/words | tail -n 300 > ./300words,这样你就可以真正理解你在做什么,避免被输出量所淹没.

      是的,这不是一个完整的答案,但可能太多了,不是吗?

      【讨论】:

      • 第二次和第三次 grep 运行可以合并,因为两者都使用-v 选项运行。
      猜你喜欢
      • 2018-12-30
      • 1970-01-01
      • 2016-02-21
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多