2

In bash, I'm trying to test whether a sentence is a pangram.

read sentence
if [[ "$sentence" == [Aa] && [Bb] && [Cc] && [Dd] && [Ee] && [Ff] && [Gg] && [Hh] && [Ii] && [Jj] && [Kk] && [Ll] && [Mm] && [Nn] && [Oo] && [Pp] && [Qq] && [Rr] && [Ss] && [Tt] && [Uu] && [Vv] && [Ww] && [Xx] && [Yy] && [Zz] ]]; then
echo "pangram"
else
echo "not pangram"
fi

This is the code I have so far, and all I'm getting is an output of "not pangram". Does anyone know what is wrong with my code?

I was trying to manipulate the code from a previous question of mine.

Community
  • 1
  • 1
Quill
  • 2,729
  • 1
  • 33
  • 44
  • Are you attempting to use regular expressions? Which part of your script tests the regular expression? – Greg Hewgill Oct 21 '14 at 01:39
  • The `==` operator does not do anything with regular expressions. The operator to do regular expression matching (in bash) is `=~`. But you can't combine regular expressions with `&&` like that. – Greg Hewgill Oct 21 '14 at 01:43
  • So using `=~`, to get the matching characters, what do I use to replace `&&` – Quill Oct 21 '14 at 01:47
  • Well you can still use `&&`, but you would have to do something unwieldy like `[[ "$sentence" =~ [Aa] && "$sentence" =~ [Bb] && ... ]]` – Greg Hewgill Oct 21 '14 at 01:48
  • Okay @GregHewgill, If you want to paste that last question as an answer, I'll mark it as correct. Thanks for all your help. :D – Quill Oct 21 '14 at 01:52

3 Answers3

2

A better and pure Bash way to test for a pangram would be (written as a function):

is_pangram() {
    local l=${1,,} i
    for i in {a..z}; do
        [[ $l = *$i* ]] || return 1
    done
    return 0
}

This function first converts its argument to lowercase: the expansion of ${1,,} is that of $1 converted to lowercase; we store this value in the local variable l. We then loop through the (lowercase alphabet) with for i in {a..z} and we use a glob (instead of a regular expression which would be overkill in this case) to check whether $l contains the letter.

Then try it:

$ if is_pangram "Cwm fjord bank glyphs vext quiz"; then echo "it's a pangram"; else echo "not a pangram"; fi
it's a pangram
$ if is_pangram "the horse jumps over the fence"; then echo "it's a pangram"; else echo "not a pangram"; fi
not a pangram
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
0

Your syntax is almost right, but needs a bit more repetition. You'll need something like:

[[ "$sentence" =~ [Aa] && "$sentence" =~ [Bb] && "$sentence" =~ [Cc] && ... ]]

There are undoubtedly more succinct ways to do this.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
0

Can you use common *nix commands, or are you restricted to pure bash operations and built-ins?

If sort is permitted, then I'd do:

#!/bin/bash

# Simple pangram tester.
# Doesn't handle non-alphabetic chars except space.

# Written by PM 2Ring 2014.10.21

is_pangram()
{
    count=$(echo -n ${1// /}|(while read -n 1 a;do echo $a;done)|sort -fu|wc -l)
    [[ $count -eq 26 ]]
}

test_pangram()
{
    if is_pangram "$1"
        then echo "'$1' is a pangram."
        else echo "'$1' is not a pangram."
    fi
}

teststrings=(
    "A quick brown fox jumps over the lazy dog"
    "This is a test" 
    "Cwm fjord bank glyphs vext quiz"
    "Is not a pangram"
)

for s in "${teststrings[@]}"
do
    test_pangram "$s"
done
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182