2

I have an array containing possible leap years and I'd like to check if a given year may belong or not to this array.

#!/bin/ksh

leap_yrs=()
for i in {1852..2010..4}; do
    leap_yrs+=("$i")
done

I've found here Check if an array contains a value the following code

year=1900
case "${leap_yrs[@]}" in *"${year}"*) 
echo "it could be a leap year"
;; 
esac

It works but I do not know why.

I would have written something like

year=1900
case "$year" in *"${leap_yrs[@]}"*) 
echo "it could be a leap year"
;; 
esac

but this does not work.

Could I have some explanation? Thanks

MatteP

Community
  • 1
  • 1
pugliam
  • 51
  • 3

1 Answers1

0

You gave a link to the source of the special code. Beneath the code you find the comment:
Note that this doesn't iterate over each element in the array separately... instead it simply concatenates the array and matches "two" as a substring. This could cause undesirable behavior if one is testing whether the exact word "two" is an element in the array. @MartyMacGyver Aug 19 '13 at 23:21

Another explanation.

Try the following commands to see what is happening (or use set -x):

echo case "${leap_yrs[@]}" in *"${year}"*

if [[ "1852 1856 1860 1864 1868 1872 1876 1880 1884 1888 1892 1896 1900 1904 1908 1912 1916 1920 1924 1928 1932 1936 1940 1944 1948 1952 1956 1960 1964 1968 1972 1976 1980 1984 1988 1992 1996 2000 2004 2008" = *1900* ]]
then
   echo "Found"
fi

if [[ ${leap_yrs[@]}  = *1900* ]]
then
   echo "Also found"
fi

When you are not sure that your shell supports if [[ ... ]], you can use the more portable case construction.
Now that you see how the match is made, you understand that year 19 might be a leap year too. A safer way is to make a string with colons like :1852:1856:...: and match with *:${year}:*.
Getting more complex to understand with each improvement? Just make a function isLeapYear (but getting off topic).

EDIT:
The * * are wildcards (stand for any characters-string). p*m matches pim, pam, program and pugliam. *8* matches 4 6 8 10 but does not match 5 7 9. In this case you can read it as substring.
I added colons, because 1 is a substring of 1868 1872 1876, but :1: is not a substring of :1868:1872:1876:

Walter A
  • 16,400
  • 2
  • 19
  • 36
  • Hi @Walter A Thanks. But then I think I have to rephrase my question. What do the * * mean? Do they isolate the substring I'm searching for? What is the meaning of the colons in defining a string? Thanks – pugliam Nov 03 '16 at 08:52