BASH Palindrome Checker

前端 未结 5 1915
[愿得一人]
[愿得一人] 2021-01-24 19:14

This is my first time posting on here so bear with me please.

I received a bash assignment but my professor is completely unhelpful and so are his notes.

Our assig

相关标签:
5条回答
  • 2021-01-24 19:36

    Ok here is something to get you started:

    I suggest to use the plan you have above, just generate the number of "." using a for loop.

    This question will explain how to make a for loop from 3 to 45:

    How do I iterate over a range of numbers defined by variables in Bash?

    for i in {3..45}; 
    do 
       * put your code above here *
    done
    

    Now you just need to figure out how to make "i" number of dots "." in your first grep and you are done.

    Also, look into sed, it can nuke the non-lowercase answers for you..

    0 讨论(0)
  • 2021-01-24 19:36

    Another solution that uses a Perl-compatible regular expressions (PCRE) with recursion, heavily inspired by this answer:

    grep -P '^(?:([a-z])(?=[a-z]*(\1(?(2)\2))$))++[a-z]?\2?$' /usr/share/dict/words
    
    0 讨论(0)
  • 2021-01-24 19:55

    Why use grep? Bash will happily do that for you:

    #!/bin/bash
    
    is_pal() {
        local w=$1
        while (( ${#w} > 1 )); do
            [[ ${w:0:1} = ${w: -1} ]] || return 1
            w=${w:1:-1}
        done
     }
    
     while read word; do
         is_pal "$word" && echo "$word"
     done
    

    Save this as banana, chmod +x banana and enjoy:

    ./banana < /usr/share/dict/words
    

    If you only want to keep the words with at least three characters:

    grep ... /usr/share/dict/words | ./banana
    

    If you only want to keep the words that only contain lowercase and have at least three letters:

    grep '^[[:lower:]]\{3,\}$' /usr/share/dict/words | ./banana
    
    0 讨论(0)
  • 2021-01-24 19:59

    The multiple greps are wasteful. You can simply do

    grep -E '^([a-z])[a-z]\1$' /usr/share/dict/words
    

    in one fell swoop, and similarly, put the expressions on grep's standard input like this:

    echo '^([a-z])[a-z]\1$
    ^([a-z])([a-z])\2\1$
    ^([a-z])([a-z])[a-z]\2\1$' | grep -E -f - /usr/share/dict/words
    

    However, regular grep does not permit backreferences beyond \9. With grep -P you can use double-digit backreferences, too.

    The following script constructs the entire expression in a loop. Unfortunately, grep -P does not allow for the -f option, so we build a big thumpin' variable to hold the pattern. Then we can actually also simplify to a single pattern of the form ^(.)(?:.|(.)(?:.|(.)....\3)?\2?\1$, except we use [a-z] instead of . to restrict to just lowercase.

    head=''
    tail=''
    for i in $(seq 1 22); do
        head="$head([a-z])(?:[a-z]|"
        tail="\\$i${tail:+)?}$tail"
    done
    grep -P "^${head%|})?$tail$" /usr/share/dict/words
    

    The single grep should be a lot faster than individually invoking grep 22 or 43 times on the large input file. If you want to sort by length, just add that as a filter at the end of the pipeline; it should still be way faster than multiple passes over the entire dictionary.

    The expression ${tail+:)?} evaluates to a closing parenthesis and question mark only when tail is non-empty, which is a convenient way to force the \1 back-reference to be non-optional. Somewhat similarly, ${head%|} trims the final alternation operator from the ultimate value of $head.

    0 讨论(0)
  • 2021-01-24 20:01

    Like this:

    for word in `grep -E '^[a-z]{3,45}$' /usr/share/dict/words`;
        do [ $word == `echo $word | rev` ] && echo $word;
    done;
    

    Output using my dictionary:

    aha
    bib
    bob
    boob
    ...
    wow
    

    Update

    As pointed out in the comments, reading in most of the dictionary into a variable in the for loop might not be the most efficient, and risks triggering errors in some shells. Here's an updated version:

    grep -E '^[a-z]{3,45}$' /usr/share/dict/words | while read -r word;
        do [ $word == `echo $word | rev` ] && echo $word;
    done;
    
    0 讨论(0)
提交回复
热议问题