0

I found a way to check with if statement that the input corresponds to a date pattern and is not a eccentric date.

Respectively:

  • if [[ $dateinput =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]
  • date -d "$dateinput"

And they work.

I tried to apply it as I can in a while loop as:

dateinput="1992-01-01" #voluntarily made in order to see if the while statement is ok
while [ ! date -d "$dateinput" ]; do
    read -p "Indicate a date please: " Date
    dateinput=$Date
done

The result is it displays the prompt's text Indicate a date please:, then displays script.sh: line 73: [[! : command not found where line 73 is : while [ ! date -d "$dateinput" ]; do. Besides the variable dateinput does not exist ever after it because it won't display echo "the input date is: ${dateinput}" but continues to read and to display the rest of lines of the script.

What can I do to execute it?


bash version: 4.4.20 | OS version: Ubuntu 18.04.3 LTS.

AvyWam
  • 890
  • 8
  • 28
  • The error message and what you say is on line 73 don't seem to agree. But apart from that: if you check exit status (which you do for `date -d`), you should _not_ wrap the command in `[ ]` or `[[ ]]`: `if ! date -d "$dateinput"; then...`, potentially with a `&>/dev/null` to silence any output. – Benjamin W. Oct 10 '19 at 15:08
  • 2>&1 is better than &> as I believe the latter isn't fully supported across shells – Neil Oct 10 '19 at 15:09
  • @Lepr Sure, but if I know that I use Bash 4.4, I like using the convenient shorthand. The script already uses a bunch of Bashisms (`=~` matching, `read -p`) – I can safely assume that `&>` will work. – Benjamin W. Oct 10 '19 at 15:48

3 Answers3

2

You can either drop the square braces or add "$()" around your date command like these:

 while [ ! "$(date -d "${dateinput}")" ]; do 
     read -p "Indicate a date please: " dateinput
 done

or

 while ! date -d "${dateinput}" > /dev/null 2>&1; do
     read -p "Indicate a date please: " dateinput
 done

You don't need > /dev/null 2>&1 but without it date output will be printed

Neil
  • 345
  • 6
  • 14
  • 1
    This doesn't handle empty `dateinput`, but is simplest. Add `&& [[ ! -z ${dateinput} ]]` to the while condition. – Bayou Oct 10 '19 at 15:57
  • I used the first example you show but modify a little to write : `while [ ! "$(date -d ${dateinput})" ]; do` but your solution works well. But to use `2>&1/dev/null` displays the error: `line 73: 1/dev/null : ambiguous redirect` and it does not accept valid date as "1992-01-01" then keeps in the loop. The first solution works well in the bash function I made. Thank you very much. – AvyWam Oct 10 '19 at 19:43
  • silly mistake on my part, it should be `> /dev/null 2>&1`, I'll edit the post. As for not accepting the date, I'm not seeing that issue with date, hopefully it's just due to that bad redirect – Neil Oct 10 '19 at 19:52
1
while test -z "$date"; do
    read -p "Indicate a date please: " dateinput;
    if [[ $dateinput =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
        date="$(date -d "$dateinput")";
        if ! test $?; then
            date=""
        fi
    fi
done
echo input date is: "$date"

The above code has a loop that keeps running while $date is empty. The code inside the loop prompts user for a date and reads $dateinput . If the user types a string that matches your pattern ([[ $dateinput =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]) then it runs date -d on it and saves the output to $date. If the date command fails to recognize a valid date from the $dateinput (! test $? will be true) then $date is set to an empty string so that the loop runs again.

This loop will stop when user enters a value which matches your pattern and also is a valid date string for the datecommand. The output of date command is saved in $date variable.

Some relevant documentation:

  1. for $?: https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-_0024_003f
  2. for the test command https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html#index-test
pii_ke
  • 2,811
  • 2
  • 20
  • 30
  • 1
    Thank you for this code snippet, which might provide some limited short-term help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its long-term value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Toby Speight Oct 10 '19 at 16:28
0

To validate the input as date, you can execute the 'date', and check the return code - using the 'if date -d "...". The '[' allow access to limited set of test operators

while true ; do
    read -p "Indicate a date please: " dateinput
    [[ "$dateinput" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$dateInput" >/dev/null && break
done
dash-o
  • 13,723
  • 1
  • 10
  • 37