1

My Syst admin prof just started teaching us bash and he wanted us to write a bash script using grep to find all 3-45 letter palindromes in the linux dictionary without using reverse. And im getting an error on my if statement saying im missing a '

UPDATED CODE:

    front='\([a-z]\)'
front_s='\([a-z]\)'
numcheck=1
back='\1'
middle='[a-z]'
count=3

while [ $count -ne "45" ]; do

    if [[ $(($count % 2)) == 0 ]]
        then
            front=$front$front_s
            back=+"\\$numcheck$back"
            grep "^$front$back$" /usr/share/dict/words
            count=$((count+1))
        else
            grep "^$front$middle$back$" /usr/share/dict/words

            numcheck=$((numcheck+1))
            count=$((count+1))
    fi

done
Conner Ney
  • 25
  • 6
  • remove ":" (or substitute with a ";") from "if" line. Also, use if [[ ... ]] (double brackets). Also in the "while" line.. – AKS Oct 31 '14 at 22:44
  • 2
    So you have the same prof as Greg (or your prof's using the same book as his): http://stackoverflow.com/questions/26601234/bash-palindrome-checker – gniourf_gniourf Oct 31 '14 at 22:46
  • 1
    Duplicate of this: http://stackoverflow.com/questions/26601234/bash-palindrome-checker – AKS Oct 31 '14 at 22:49
  • Thanks again arun, but my script is different than his. And i think im close to getting it running. any input? – Conner Ney Oct 31 '14 at 22:56
  • If your ? is to find all words from lenght 3 to 45 in words file (in Linux/Unix) which are palindrome.. and you don't have to use "rev" (reverse) function, then see my answer as that's all what you need. You can align it better than me. I used "[[:alnum:]]" as it can search/works for words like: P2P. But, if you want even more control (like P2p should be considered as a palindrome), then use: w="$(echo $w | tr [A-Z] [a-z])"; within for loop (just after word "do" and before word "if". – AKS Oct 31 '14 at 23:05

2 Answers2

1

You have four obvious problems here:

  • First about a misplaced and unescaped backslash:

    back="\\$numcheck$back" # and not back="$numcheck\$back"
    
  • Second is that you only want to increment numcheck if count is odd.
  • Third: in the line

     front=$front$front
    

    you're doubling the number of patterns in front! hey, that yields an exponential growth, hence the explosion Argument list too long. To fix this: add a variable, say, front_step:

    front_step='\([a-z]\)'
    front=$front_step
    

    and when you increment front:

    front=$front$front_step
    

With these fixed, you should be good!

The fourth flaw is that grep's back-references may only have one digit: from man grep:

Back References and Subexpressions
   The back-reference \n, where n is a single digit, matches the substring
   previously  matched  by  the  nth  parenthesized  subexpression  of the
   regular expression.

In your approach, we'll need up to 22 back-references. That's too much for grep. I doubt there are any such long palindromes, though.

Also, you're grepping the file 43 times… that's a bit too much.

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
  • Thanks gniourf, i made your alterations, but am still getting an error with line 23 + 27 "/bin/grep: Argument list too long" – Conner Ney Oct 31 '14 at 23:26
  • Yep, I found this now.. he should stop putting front=$front$front once counter becomes -gt 22 – AKS Oct 31 '14 at 23:55
  • Agree with front_step variable approach. – AKS Oct 31 '14 at 23:56
  • Thanks for the great edit you guys have been great, althought my code still doesnt seem to be working. It only prints 3 letter palindromes. See my updated code – Conner Ney Nov 01 '14 at 00:45
  • @ConnerNey Well, you have a `+` character in the line `back=+"\\$numcheck$back"`. Remove it and it should work. – gniourf_gniourf Nov 01 '14 at 00:47
0

Try this:

#!/bin/bash

 for w in `grep -E "^[[:alnum:]]{3,45}$" /usr/share/dict/words`; do if [[ "$w" == "`echo $w|sed "s/\(.\)/\1\n/g"|tac|tr -d '\012'`" ]]; then echo "$w == is a palindrome"; fi; done

OR

#!/bin/bash

front='\([a-z]\)'
numcheck=1
back='\1'
middle='[a-z]'
count=3

while [ $count -ne "45" ]; do

    if [[ $(($count % 2)) == 0 ]]
        then
            front=$front$front
            back="\\$numcheck$back"
            grep "^$front$back$" /usr/share/dict/words
        else
            grep "^$front$middle$back$" /usr/share/dict/words

            ## Thanks to gniourf for catching this.
            numcheck=$((numcheck+1))
    fi

    count=$((count+1))
    ## Uncomment the following if you want to see one by one and run script using bash -x filename.sh
    #echo Press any key to continue: ; read toratora;

done
AKS
  • 16,482
  • 43
  • 166
  • 258
  • Thanks again Arun, but i have to keep this format of a script. I saw him during office hours today and said this is almost exactly what he wants. It just has to run. So any additions/subtractions to my code would really help. thanks again – Conner Ney Oct 31 '14 at 23:07
  • if you run your script with "bash -x yourscript.sh", you'll know why you see that error message (too long ...). Your variables are not doing anything in the script (as you can use $var in grep command where single quote ' ' is used also, patterns won't work either with single quote. – AKS Oct 31 '14 at 23:14
  • There's a limit for the pattern size that you can give in grep command. you can't give: grep "something_longer_than_universe_size_pattern" words file. When I faced this similar issue in past, I had to put the pattern part in another file and had to use "fgrep" command. – AKS Oct 31 '14 at 23:16
  • Not sure what you mean, I'm running it in an ubuntu terminal with rbash myfile.sh – Conner Ney Oct 31 '14 at 23:21
  • I do understand the variable size though, and thought id encounter this problem. – Conner Ney Oct 31 '14 at 23:22
  • Arun, Great edit! although running it with rbash gets me much farther than before, it stops after the palindrome "revolver" and give errors of lines 15 + 17 "/bin/grep: Argument list too long" – Conner Ney Oct 31 '14 at 23:37
  • try: rbash debug mode (rbash -x yourfile.sh) and see what it spits on STDOUT. You'll see the pattern (grep pattern file) part is expanding and crossing its limits, when counter reaches 40+ or so. – AKS Oct 31 '14 at 23:37