Syntax error near unexpected token `/' when substracting timestamps - bash

I'm totally new to bash and unix, so the answer to this might be very simple, but despite googling for quite some time I didn't find the solution.
What I'm trying to do is to calculate a difference in days between 2 dates. However, when I convert each date to an epoch second and try to subtract them I get the "Syntax error near unexpected token `/" error.
Here's the script:
# obtain date provided by user in the following format "YYYY-MM-DD"^M
POPULATE_FROM=$2^M
POPULATE_TO=$3^M
#obtain task name^M
TASK=$1^M
FILE_NAME=$(echo $TASK | cut -d'.' -f1)^M
# obtain current date^M
CURRENT_DATE=$(date +%Y-%m-%d)^M
echo "Current $CURRENT_DATE"^M
POPULATE_FROM_DATE=$(date -d "$POPULATE_FROM" +%s)^M
CURRENT_DAY=$(date -d "$CURRENT_DATE" +%s)^M
POPULATE_TO_DATE=$(date -d "$POPULATE_TO" +%s)^M
echo "Current date $CURRENT_DAY"^M
echo "Populate From date $POPULATE_FROM_DATE"^M
echo "Populate to date $POPULATE_TO_DATE"^M
# calculate dates difference in days^M
DIFF_FROM=($POPULATE_FROM_DATE - $CURRENT_DAY) / 86400^M
echo $DIFF_FROM^M
DIFF_TO=($POPULATE_TO_DATE - $CURRENT_DAY) / 86400^M
if ((DIFF_FROM < 0)) ; then^M
# revert it so difference is a positive int^M
DIFF_FROM=$((0-$DIFF_FROM))^M
DIFF_TO=$((0-$DIFF_TO))^M
for ((i=$DIFF_FROM;i>$DIFF_TO;i--));^M
do^M
TASK_DATE="$(date "+%Y-%m-%d" -d "$i days ago")"^M
TEMP_FILE_NAME="$FILE_NAME-$TASK_DATE.json"^M
echo $TEMP_FILE_NAME^M
^M
# copy content of the base task to a new file in order not to overwrite it^M
cp $TASK $TEMP_FILE_NAME^M
^M
TASK_NAME="$FILE_NAME-$TASK_DATE"^M
sed -i "s/$FILE_NAME/$TASK_NAME/" $TEMP_FILE_NAME^M
^M
# replace "T-1" with "T-i"^M
DAY_PATTERN='"IMAS.Loaders.Date" : "T-1"'^M
NEW_DAY_PROPERTY='"IMAS.Loaders.Date" : "'"T-$i"'"'^M
sed -i "s/$DAY_PATTERN/$NEW_DAY_PROPERTY/" $TEMP_FILE_NAME^M
^M
# remove the scheduled cron expression^M
sed -i '/ScheduleExpression/d' $TEMP_FILE_NAME^M
^M
done^M
else^M
echo "Provided date is in the future, no action performed"^M
fi^M
Here's the execution:
bash script.sh "fileName" "2019-08-20" "2019-08-21"
And here's the output I get:
Current 2019-08-22
Current date 1566428400
Populate From date 1566255600
Populate to date 1566342000
")syntax error: invalid arithmetic operator (error token is "line 17: 1566255600
")syntax error: invalid arithmetic operator (error token is "line 19: 1566342000
'script.sh: line 24: syntax error near unexpected token `
'script.sh: line 24: ` for ((i=$DIFF_FROM;i>$DIFF_TO;i--));
Any ideas what am I doing wrong?

As it says, line 17 is wrong.. Its not a valid syntax.
Use this:
DIFF_FROM=$(($(($POPULATE_FROM_DATE - $CURRENT_DAY)) / 86400))
This line define the DIFF_FROM variable which will be used in the other lines below.

Related

Not able to get the expected date output after adding a second

What I'm trying to do below
echo -e "input start_time(YYYYMMDDHHMMSS)"
read word1
dt= `date "--date=${word1} -s + 1sec" +%Y%m%d%H%M%S`
echo ${dt}
If input : 20181201090909 then I got an output : 20181201090909030001. The expected output is quite incorrect. I was expecting it to be 20181201090910
You need to format differently the string you pass to date:
~$ date +%Y%m%d%H%M%S --date="20181201 09:09:09 + 1sec"
20181201090910
~$
You see a space between the date and the time, and the colon separating hour minutes seconds. See info date for more information.

How to suppress leading zero in date output?

I have this code:
printf -v s '%(%S)T' -1 # grab the current second
if ((s == 0)); then
# at the top of the minute, run some code
fi
This code throws an error on the eighth and ninth second of every minute:
bash: ((: 08: value too great for base (error token is "08")
bash: ((: 09: value too great for base (error token is "09")
How can I rectify this? Basically, we need to suppress the leading zero in the date output generated by printf.
Use a - prefix in the format string, thus:
printf -v s '%(%-S)T' -1
This suppresses the leading zero.
A more generic way of solving this is to specify the base in Bash arithmetic this way, while keeping the printf command unchanged:
if ((10#$s == 0)); then
Related post on Unix & Linux Stack Exchange:
Removing leading zeros from date

multiplication date by minutes in bash

i have to multiply day by one day minutes
for example today date 2014/08/04
date=4
totalNumberOfminutesPerDay=1440
4*1440
variable=$(date +"%Y.%m.$((%d*1440))");
this gives me this error
-bash: %d*1440: syntax error: operand expected (error token is "%d*1440")
variable=$(date '+%Y.%m.')$(( $(date '+%e') * 1440 ))
Using +%d would fail:
$ (( $(date -d 2014-08-08 '+%d') * 1440 ))
bash: ((: 08: value too great for base (error token is "08")
It is not possible to do the multiplication in date's format string.
You have to do a seperate calculation as fedorqui mentioned in his comment:
variable=$(date +"%Y.%m.$(( $(date +%e)*1440))");
If you want "variable" to be 5760, the following statement is sufficient.
variable=$(( $(date +%e)*1440));

Get Day Of Week in bash script

I want to have the day of week in the variable DOW.
So I use the following bash-script:
DOM=$(date +%d)
DOW=($($DOM % 7) ) | sed 's/^0*//'
Unfortunately there I get this error: bash: 09: command not found. The expected result is 2 ( 9 % 7 = 2) in the variable $DOW.
How can I get this working?
It works for the days 1-8 but because of the C-hex, there is no number over 8 available and the following message appears: bash: 09: value too great for base (error token is "09").
Use %u. Like this:
DOW=$(date +%u)
From the man page:
%u day of week (1..7); 1 is Monday
You can also use to return the day name
date +'%A'
Using a different %-specifier is the real answer to your question. The way to prevent bash from choking on invalid octal numbers is to tell it that you actually have a base-10 number:
$ DOM=09
$ echo $(( DOM % 7 ))
bash: 09: value too great for base (error token is "09")
$ echo $(( 10#$DOM % 7 ))
2
This works fine here
#!/bin/sh
DOW=$(date +"%a")
echo $DOW
The format option %u returns weekday number [1..7]. Monday is 1.
With date in string:
$ date -d "2022-07-17" +%u
7
Also check return value in $?.
For invalid date, $? is nonzero.
You can use the - flag:
DOM=$(date +%-d)
^
which would prevent the day from being padded with 0.
From man date:
- (hyphen) do not pad the field
Observe the difference:
$ DOM=$(date +%d)
$ echo $((DOM % 7))
bash: 09: value too great for base (error token is "09")
$ DOM=$(date +%-d)
$ echo $((DOM % 7))
2

Bash script: using variables / parameter in sed

I am trying to write a little bash script, where you can specify a number of minutes and it will show the lines of a log file from those last X minutes.
To get the lines, I am using sed
sed -n '/time/,/time/p' LOGFILE
On CLI this works perfectly, in my script however, it does not.
# Get date
now=$(date "+%Y-%m-%d %T")
# Get date minus X number of minutes -- $1 first argument, minutes
then=$(date -d "-$1 minutes" +"%Y-%m-%d %T")
# Filter logs -- $2 second argument, filename
sed -n '/'$then'/,/'$now'/p' $2
I have tried different approaches and none of them seem to work:
result=$(sed -n '/"$then"/,/"$now"/p' $2)
sed -n "/'$then'/,/'$now'/p" "$2"
sed -n "/$then/,/$now/p" $2
sed -n "/$then/,/$now/p" "$2
Any sugesstions?
I am on Debian 5, echo $SHELL says /bin/sh
EDIT : The script produces no output, so there is no error showing up.
In the logfile every entry starts with a date like this 2013-05-15 14:21:42,794
I assume that the main problem is that you try to perform an arithmetic comparison by string matching. sed -n '/23/,/27/p' gives you the lines between the first line that contains 23 and the next line that contains 27 (and then again from the next line that contains 23 to the next line that contains 27, and so on). It does not give you all lines that contain a number between 23 and 27. If the input looks like
19
22
24
26
27
30
it does not output anything (since there is no 23). An awk solution that uses string matching has the same problem. So, unless your then date string occurs verbatim in the log file, your method will fail. You have to convert your date strings into numbers (drop the -, <space>, and :) and then check whether the resulting number is in the right range, using an arithmetical comparison rather than a string match. This goes beyond the capabilities of sed; awk and perl can do it rather easily. Here is a perl solution:
#!/bin/bash
NOW=$(date "+%Y%m%d%H%M%S")
THEN=$(date -d "-$1 minutes" "+%Y%m%d%H%M%S")
perl -wne '
if (m/^(....)-(..)-(..) (..):(..):(..)/) {
$date = "$1$2$3$4$5$6";
if ($date >= '"$THEN"' && $date <= '"$NOW"') {
print;
}
}' "$2"
Don't give yourself a headache with nested quotes. Use the -v option with awk to pass the value of a shell variable into the script:
#!/bin/bash
# Get date
now=$(date "+%Y-%m-%d %T")
# Get date minus X number of minutes -- $1 first argument, minutes
delta=$(date -d "-$1 minutes" +"%Y-%m-%d %T")
# Filter logs -- $2 second argument, filename
awk -v n="$now" -v d="$delta" '$0~n,$0~d' $2
Also don't use variable names of shell builtins i.e then.

Resources