LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-12-2015, 02:40 PM   #1
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 921

Rep: Reputation: 46
Bash 101 while loop fail


Ladies and Gents,

Still failing bash 101

I am a copy/paste person and don't really know how to write code. I only know what I want it to do. Most of the code below comes from other working scripts with a few small changes relevant to what I am trying to do. Since the code doesn't work my changes are a "fail".

What this code is suppose to do is take the input day and check to see if it is a Jewish Holiday. So the civil date needs to be converted to a Hebrew date. Hdate will do that and output the Hebrew Holiday, or a blank line.

For example
Code:
:~$ hdate -dhq 5 3 2015 

Thursday, 5 March 2015, 14 Adar 5775
Purim
:~$
So I need the 3rd line of the output, or at least I think it is the third line. That's where the data I need is if I redirect the output to a file. I am trying to test if that line has data or is blank. If blank, then loop to check the next day and so on for 7 days.

If there is data in that line then I am trying to compare it to a cvs data file with a listing of the Jewish Holidays to get other data so automated events (not implemented yet) can be scheduled for that day based on that data.

The Code:
Code:
#!/bin/bash

STORDIR="${HOME}/bin/shabbat/data"
set -x
DAY=5
MONTH=3
YEAR=2015

i=1
  while [ $i -lt 7 ]; do
    YOMTOVE=`echo "$(hdate -dhq $DAY $MONTH $YEAR)" | head -n 3 | tail -n +3 `
    echo "$YOMTOVE"
    if [[ "$YOMTOVE" != "" ]]; then  
      grep ^"$YOMTOVE" "$STORDIR"/YomTove.cvs
    i=$[$i+1]
    DAY=$[$DAY+1]
    fi
  done
When I run this my shell goes into a open ended loop with this type of output.
Code:
+ [[ '' != '' ]]
+ '[' 3 -lt 7 ']'
++ head -n 3
++ tail -n +3
+++ hdate -dhq 7 3 2015
++ echo '
Saturday, 7 March 2015, 16 Adar 5775'
+ YOMTOVE=
+ echo ''

+ [[ '' != '' ]]
+ '[' 3 -lt 7 ']'
++ head -n 3
++ tail -n +3
+++ hdate -dhq 7 3 2015
++ echo '
Saturday, 7 March 2015, 16 Adar 5775'
+ YOMTOVE=
+ echo ''

+ [[ '' != '' ]]
After a reboot the code checks the correct date (5 March 2015) the second time the code is run it checks an incorrect date (7 March 2015). No idea why. It also does not seem to be stepping through the while loop.

Last edited by rbees; 02-12-2015 at 02:42 PM. Reason: formating
 
Old 02-12-2015, 03:03 PM   #2
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: Fedora
Posts: 4,140

Rep: Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263
Shalom,
Your problem is the way you are trying to pick out the 3rd record. A simpler way is to use awk to just print the 3rd line:

Code:
echo "$(hdate -dhq $DAY $MONTH $YEAR)" | awk 'NR == 3'
Also, your increment probably needs to be outside the if statement. Right now it only increments when YOMTOVE is not blank.
Code:
    if [[ "$YOMTOVE" != "" ]]; then  
        grep ^"$YOMTOVE" "$STORDIR"/YomTove.cvs
    fi
    i=$(( i + 1 ))
 
1 members found this post helpful.
Old 02-12-2015, 03:32 PM   #3
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 921

Original Poster
Rep: Reputation: 46
Thanks smallpond, Alechem Shalom

That did it.

What is the best way to make it step over a new month? Something like running a check on $DAY and if it is larger than 28 somehow test $MONTH to see when it will change. Guess I will have to think on it some.
 
Old 02-12-2015, 09:23 PM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
smallpond has helped with the issue, may I suggest some cosmetic changes which may also help in making things clearer
Code:
while [ $i -lt 7 ]; do
...
i=$[$i+1]
done

for (( i = 1; i < 7; i++)); do
...
done
##########
YOMTOVE=`echo "$(hdate -dhq $DAY $MONTH $YEAR)" | head -n 3 | tail -n +3 `

YOMTOVE=$(hdate -dhq $DAY $MONTH $YEAR | awk 'NR==3')
# only a modification to smallpond's suggestion
##########
if [[ "$YOMTOVE" != "" ]]; then

if [[ -n "$YOMTOVE" ]]; then
##########
DAY=$[$DAY+1]

(( DAY++ ))
 
1 members found this post helpful.
Old 02-13-2015, 08:19 AM   #5
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 921

Original Poster
Rep: Reputation: 46
Thanks grail

I like that, it looks cleaner too. On the plus side I actually understand what it does.

But now by trying to account for leap years I have made it not work again and I don't understand why. I am getting
Code:
:~$ bin/shabbat/test
bin/shabbat/test: line 90: syntax error near unexpected token `}'
bin/shabbat/test: line 90: `}'
My guess is that I am not following the logic through correctly and I have too many, or not enough "fi" in the right place.

The Current code
Code:
#!/bin/bash

STORDIR="${HOME}/bin/shabbat/data"
DAY=28
MONTH=1
YEAR=2016

# Calculate next day accounting for leap years
function Next_Day
{
  if [[ "$DAY" -le "27" ]]; then
    let i=i+1
    let DAY=DAY+1
    exit
    
  elif [[ "$DAY" = "28" ]]; then
    case ${ $MONTH } in
      1) 
      FULL="31"
      ;;
      2)
      FULL="28"
      ;;
      3)
      FULL="31"
      ;;
      4) 
      FULL="30"
      ;;
      5)
      FULL="31"
      ;;
      6)
      FULL="30"
      ;;
      7) 
      FULL="31"
      ;;
      8)
      FULL="31"
      ;;
      9)
      FULL="30"
      ;;
      10) 
      FULL="31"
      ;;
      11)
      FULL="30"
      ;;
      12)
      FULL="31"
      ;;
    esac

    if [[ $MONTH == "2" ]];then
      rem1=$((YEAR%4))
      rem2=$((YEAR%100))
      rem3=$((YEAR%400))

    if [ ${rem3} = "0" ];then
      $FULL="29"
      exit
      fi
  
    if [ ${rem2} = "0" -a ${rem3} != "0" ];then
      # echo "$YEAR Is Not A Leap Year"
      exit
      fi

    if [ ${rem1} = "0" -a ${rem2} != "0" ];then
      # echo "$YEAR Is A Leap Year"
      $FULL="29"
      else
      # echo "$YEAR Is Not A Leap Year"
      exit
    fi
  fi
      
  if [ ${DAY} = ${FULL} -a ${MONTH} -lt "12" ]; then
    let MONTH=MONTH+1
    let DAY=1
    exit

  elif [ ${DAY} = ${FULL} -a ${MONTH} = "12" ];then
    let YEAR=YEAR+1
    let MONTH=1
    let DAY=1
    exit  
  fi
}

################# 
# # Main Code # #
#################

for (( i = 1; i < 7; i++)); do
    
    YOMTOVE=$(hdate -dhq $DAY $MONTH $YEAR | awk 'NR==3')
    echo "$YOMTOVE"
    if [[ -n "$YOMTOVE" ]]; then
      grep ^"$YOMTOVE" "$STORDIR"/YomTove.cvs
      # actions based on what holiday it is
    fi
done
Next_Day

exit
 
Old 02-13-2015, 09:19 AM   #6
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 921

Original Poster
Rep: Reputation: 46
I went through the logic for the 100th time and made some more changes and cleaned the code up a little but I am still getting the same thing.
Code:
#!/bin/bash

STORDIR="${HOME}/bin/shabbat/data"
DAY=28
MONTH=1
YEAR=2016

# Calculate next day accounting for leap years
function Next_Day
{
  case ${ $MONTH } in
      1) 
      FULL="31"
      ;;
      2)
      FULL="28"
      ;;
      3)
      FULL="31"
      ;;
      4) 
      FULL="30"
      ;;
      5)
      FULL="31"
      ;;
      6)
      FULL="30"
      ;;
      7) 
      FULL="31"
      ;;
      8)
      FULL="31"
      ;;
      9)
      FULL="30"
      ;;
      10) 
      FULL="31"
      ;;
      11)
      FULL="30"
      ;;
      12)
      FULL="31"
      ;;
  esac

  if [[ "$DAY" -le "27" ]]; then
    (( DAY++ ))
    exit
    
  elif [[ ${MONTH} == "2" ]]; then
      rem1=$((YEAR%4))
      rem2=$((YEAR%100))
      rem3=$((YEAR%400))

      if [ ${rem3} = "0" ]; then
	$FULL="29"
	exit
      fi
  
      if [ ${rem2} = "0" -a ${rem3} != "0" ]; then
	# echo "$YEAR Is Not A Leap Year"
	exit
      fi

      if [ ${rem1} = "0" -a ${rem2} != "0" ]; then
	# echo "$YEAR Is A Leap Year"
	$FULL="29"
      else
	# echo "$YEAR Is Not A Leap Year"
	exit
      fi
  
      if [ ${DAY} = ${FULL} -a ${MONTH} -lt "12" ]; then
	(( MONTH++ ))
	(( DAY++ ))
	exit
      fi

      elif [ ${DAY} = ${FULL} -a ${MONTH} = "12" ]; then
	(( YEAR++ ))
	let MONTH=1
	let DAY=1
	exit  
      fi
  exit
  fi
}

################# 
# # Main Code # #
#################

for (( i = 1; i < 7; i++)); do
    
    YOMTOVE=$(hdate -dhq $DAY $MONTH $YEAR | awk 'NR==3')
    echo "$YOMTOVE"
    if [[ -n "$YOMTOVE" ]]; then
      grep ^"$YOMTOVE" "$STORDIR"/YomTove.cvs
      # actions based on what holiday it is
    fi
done
Next_Day

exit
 
Old 02-13-2015, 11:30 AM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Yes your if's are out of balance. Placing just the if's in vim and formatting it tells me that the last fi is not required, ie the one after exit.
However, I would guess that you have put an additional one in earlier, maybe before the last elif???

Also, you use the round brackets for the for loop and incrementing but then not for testing your values. Whenever working with numbers in bash, use your round brackets, eg.
Code:
elif [ ${DAY} = ${FULL} -a ${MONTH} = "12" ]; then

elif (( DAY == FULL && MONTH == 12 )); then
You can also use standard arithmetic symbols, such as <,>, <= and so on
 
1 members found this post helpful.
Old 02-13-2015, 12:41 PM   #8
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 921

Original Poster
Rep: Reputation: 46
Thanks,

You know I have looked that over 100 times and still didn't see that extra fi.

Quote:
Whenever working with numbers in bash, use your round brackets,
But it don't seem to work.

Code:
:~$ bin/shabbat/test
bin/shabbat/test: line 54: syntax error near unexpected token `then'
bin/shabbat/test: line 54: `  else (( MONTH == 2 )); then'
:~$ bin/shabbat/test
bin/shabbat/test: line 54: syntax error near unexpected token `then'
bin/shabbat/test: line 54: `  else (( MONTH = 2 )); then'
 
Old 02-13-2015, 01:34 PM   #9
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 921

Original Poster
Rep: Reputation: 46
the current code
Code:
#!/bin/bash

STORDIR="${HOME}/bin/shabbat/data"
DAY=28
MONTH=1
YEAR=2016

# Calculate next day accounting for leap years
function Next_Day
{
  case $MONTH in [13578] | 1[02] ) FULL=31;;
    [469] | 1[01] ) FULL=30;;
    2) FULL=28;;
  esac

  if (( DAY <= 27 )); then
    (( DAY++ ))
    exit
    
  else (( MONTH = 2 )); then
      rem1=$((YEAR%4))
      rem2=$((YEAR%100))
      rem3=$((YEAR%400))

      if (( rem3 == 0 )); then
	FULL="29"
	exit
      fi
  
      if (( rem2 == 0 && rem3 != 0 )); then
	FULL="28"
	exit
      fi

      if (( rem1 == 0 && rem2 != 0 )); then
	FULL="29"
      else
	FULL="28"
	exit
      fi
  
      if (( DAY == FULL && MONTH < 12 )); then
	(( MONTH++ ))
	(( DAY++ ))
	exit

      elif (( DAY == FULL && MONTH == 12 )); then
	(( YEAR++ ))
	let MONTH=1
	let DAY=1
	exit  
      fi
  exit
  fi
}

################# 
# # Main Code # #
#################

for (( i = 1; i < 7; i++)); do
    
    YOMTOVE=$(hdate -dhq $DAY $MONTH $YEAR | awk 'NR==3')
    echo "$YOMTOVE"
    if [[ -n "$YOMTOVE" ]]; then
      grep ^"$YOMTOVE" "$STORDIR"/YomTove.cvs
      # actions based on what holiday it is
    fi
done
Next_Day

exit
 
Old 02-13-2015, 02:52 PM   #10
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 921

Original Poster
Rep: Reputation: 46
I did get it figured out. Now I have a different problem. Time for a new thread with a more relevant topic

Thanks again
 
Old 02-14-2015, 02:25 AM   #11
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Please remember to mark your threads as SOLVED.

I would also suggest an editor that has syntax highlighting as all I did was place your code in vim and format it
 
Old 02-14-2015, 09:59 AM   #12
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,863
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Another suggestion:

instead of this:
Code:
elif [ ${DAY} = ${FULL} -a ${MONTH} = "12" ]; then
I suggest this:
Code:
elif [ "$DAY" = "$FULL" -a "$MONTH" = '12' ]; then
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 9 07-28-2015 03:49 PM
[SOLVED] bash while loop fail rbees Programming 13 10-05-2014 05:14 PM
Bash script issue (for loop inside a loop) Mperonen Programming 3 08-08-2013 02:14 AM
[SOLVED] Bash - While Loop reading from two lists simultaneously - nested while loop wolverene13 Programming 11 10-01-2011 05:00 PM
bash loop within a loop for mysql ops br8kwall Programming 10 04-30-2008 03:50 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:29 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration