I am attempting the Pangram excercise. There is a read command that puts user input into the array sentence.
But what is wrong with this while loop? I get 26 lines of : command not found
alphabet=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
for char in "${!alphabet[@]}"
16
17 do
18
19 while "${sentence[char]}" -ne "${alphabet[i]}"
20 do
21 ((i++))
22 done
23
24 ((pangram_counter++))
25
26 done
read reads from STDIN which will likely cause the tests to timeout (since nothing is writing to STDIN) even if everything else works.
while takes a command. Whatever "${sentence[char]}" expands to it likely not a valid command. a and b and c etc are all not commands, as far an I know.
isn’t a valid command, both arguments between quotes will be replaced by their values (if any) and executed as if you had written the values directly into a line of a script or on the command line. Your message error come from this construction.
Anyway, what you probably want in this case is:
while [[ "${sentence[char]}" -ne "${alphabet[i]} ]]
This will lead you to other problems in this script, but it’s good to solve one problem at a time.
For instance, you can debug your script using set -x.
That means you have a file with DOS-style \r\n line endings.
Bash splits the script file on newlines. The carriage return is not a special character. Bash thinks it is part of the command to run. Since it can’t find a command that literally ends with the \r character, bash emits a “command not found” error.
The format of that error message is
bash: %s: command not found
Due to the carriage return, the cursor goes back to the start of the line and the first part of the error message is overwritten.
read -a sentence reads a line of data from the STDIN file handle. The -a means it takes that data, splits it into words and stores the results in the sentence array.
read reads lines of data from STDIN. There needs to be something writing data to STDIN in order for read to get data out of STDIN. The unit tests do not write data to STDIN. If you try to read data from STDIN and there is no data there, the read blocks (waits) until there is data … or the tests time out.
Characters are fixed. You can’t increment the character “a”. “a” is “a”.
Are you trying to count occurrences of characters? You can use an associative array (dictionary, map) to count how many times you found a string (aka character when the string is one character long).
((i++)) increments the integer variable i.
((i + 1)) evaluates the value of whatever is stored in i plus one. It returns “true” if i + 1 is non-zero, ie if i is not -1.
(( ${assoc_array["some_string"]}++ )) increments the value of "some_string" in an assoc_array by one. You can use a variable in place of a fixed string, too: (( ${assoc_array[var]}++ ))
1.) "${alphabet[i]}" is based off of the array, alphabet
This code is an attempt at the pangram excercise.
2.) The while statement compares each character of char against each character of alphabet. While they’re not equal, i is supposed to be incremented to cycle through the alphabet array. When they are equal, pangram_counter is supposed to be incremented.
3.) char cycles through the input of the positional parameters, which I have used f e d c b a as a test.
I’ve tried to get i to increment, but i can’t get it to work. It’s supposed to cycle through the alphabet array; a-z, but as @IsaacG said, you can’t increment characters, so I’m not sure what to do.
alphabet=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
8
13
14 pangram_counter=0
15 i=0
16
17 for char in "$@"
18
19 do
20
21 while [[ "${char}" -ne "${alphabet[i]}" ]]
24
25 do
26 echo "while test"
27 ((i++))
28 done
29
30 ((pangram_counter++))
31 echo "p_counter is $pangram_counter"
32 echo "i is $i"
33 echo "char is $char"
34
35 done
Running a combination of set -x, and some debug statements, you can see that the while statement does make the intended comparison, char is getting the correct characters from the positional parameters, and the pangram_counter is being incremented correctly:
bash pangram f e d c b a
+ alphabet=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
+ pangram_counter=0
+ i=0
+ for char in "$@"
+ [[ f -ne a ]]
+ (( pangram_counter++ ))
+ echo ' p_counter is 1'
p_counter is 1
+ echo ' i is 0'
i is 0
+ echo 'char is f'
char is f
+ for char in "$@"
+ [[ e -ne a ]]
+ (( pangram_counter++ ))
+ echo ' p_counter is 2'
p_counter is 2
+ echo ' i is 0'
i is 0
+ echo 'char is e'
char is e
+ for char in "$@"
+ [[ d -ne a ]]
+ (( pangram_counter++ ))
+ echo ' p_counter is 3'
p_counter is 3
+ echo ' i is 0'
i is 0
+ echo 'char is d'
char is d
+ for char in "$@"
+ [[ c -ne a ]]
+ (( pangram_counter++ ))
+ echo ' p_counter is 4'
p_counter is 4
+ echo ' i is 0'
i is 0
+ echo 'char is c'
char is c
+ for char in "$@"
+ [[ b -ne a ]]
+ (( pangram_counter++ ))
+ echo ' p_counter is 5'
p_counter is 5
+ echo ' i is 0'
i is 0
+ echo 'char is b'
char is b
+ for char in "$@"
+ [[ a -ne a ]]
+ (( pangram_counter++ ))
+ echo ' p_counter is 6'
p_counter is 6
+ echo ' i is 0'
i is 0
+ echo 'char is a'
char is a
Although i never increments, and the while loop section never runs.
OK, bash is weird with arithmetic. Because you’re using an arithmetic operator -ne bash evaluates the expression in an arithmetic context. In such a context, bash allows you to use variables without a $. This allows for tidier C-like arithmetic expressions.
But what bash is doing here is comparing the fvariable to the avariable. And when an unset variable is used in an arithmetic expression, bash substitutes the value zero.
“zero -ne zero” is false, and the while loop is not entered.
Looking at the logic of your counters: suppose the first argument is z. You intend to increment i until “z” equals argument[i]. What happens for the next argument? What is i at the start of that loop iteration?
The logic of the loop works; I’ve looked at the output with a combination of echo statements and debugging mode, and everything works, accept for the input.
I can’t find a way to enter a sentence, and have the loop cycle through it char by char, and hopefully ignore spaces. I’ve tried Positional parameters, Read, and Substring Expansion {sentence:i:1}.
The best I can get is using Positional parameters, and feeding it individual chars, space by space; z y x w v u t... - that works perfectly.
#!/bin/bash
2
5 alphabet=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
11 pangram_counter=0
12
14 for char in $@
15
17 do
18
19 i=0
20
22 while [[ "${char}" != "${alphabet[i]}" ]]
23
24 do
28 ((i++))
31 done
32
33 ((pangram_counter++))
34
38 done
41
45
46 if [[ "$pangram_counter" -eq "${#alphabet[@]}" ]]
then
49 echo "Your sentence IS a Pangram."
50
51 else
52 echo "Your sentence IS NOT a Pangram."
53
54 fi
Does anyone have a suggestion on how to take the input as a natural sentence, spaces and all? Like the example given in the excercise “The quick brown fox jumped over the lazy dog.”