I am calculating how much time my code is taking in shell script -
date1=$(date +"%s")
# some code here
date2=$(date +"%s")
diff=$(($date2-$date1))
echo "Time Taken - $(($diff / 60)) minutes and $(($diff % 60)) seconds elapsed."
Above script prints out time taken in minutes and seconds. How can I add it for hours as well? Meaning it should print out Time Taken - 0 hours 54 minutes 0 seconds something like this.
Try this:
echo "Time Taken - $((diff /60/60)) hours and $(($diff % 60)) minutes and $(($diff % 60)) seconds elapsed."
if you're starting with integer seconds that all fall within a single day, and only need HH:MM:SS, here's a very strange way to use jot + bc :
jot -w 'obase = 60; ' - 91 86400 9091 | bc
01 31
02 33 02
05 04 33
07 36 04
10 07 35
12 39 06
15 10 37
17 42 08
20 13 39
22 45 10
Related
I have a log file that shows switch time between my scripts:
Tue Oct 24 11:57:54 IRST 2017 Script switched from abc to XYZ
Tue Oct 24 14:03:41 IRST 2017 Script switched from XYZ to ZEN
Tue Oct 24 15:43:16 IRST 2017 Script switched from ZEN to XYZ
Tue Oct 24 17:07:25 IRST 2017 Script switched from XYZ to ZEN
Tue Oct 24 18:40:48 IRST 2017 Script switched from ZEN to XLS
Tue Oct 24 19:52:26 IRST 2017 Script switched from XLS to XYZ
Tue Oct 24 20:20:30 IRST 2017 Script switched from XYZ to ZEN
Tue Oct 24 20:36:06 IRST 2017 Script switched from ZEN to XLS
Tue Oct 24 21:01:03 IRST 2017 Script switched from XLS to XYZ
Tue Oct 24 21:47:47 IRST 2017 Script switched from XYZ to ZEN
How do I get total time spent on each script with bash
So the output shows like this:
abc 2 hours 30 min 40 sec
XYZ 3 hours 23 min 45 sec
zen ...
XLS ...
Assuming you have a log file named test.txt, following script should work,
#!/bin/bash
dtime=0
sname=""
while read line
do
_dtime=$(echo "$line" | awk '{print $1,$2,$3,$4}')
_sname=$(echo "$line" | awk '{print $10}')
_dtimesec=$(date +%s -d "$_dtime")
_timediff=$(( _dtimesec - dtime ))
[ "x$sname" != "x" ] && printf "$sname %d hours %d minutes %d seconds\n" $(($_timediff/3600)) $(($_timediff%3600/60)) $(($_timediff%60))
dtime=$_dtimesec
sname=$_sname
done < test.txt
This will produce an output like the following:
]$ ./test
abc 2 hours 5 minutes 47 seconds
XYZ 1 hours 39 minutes 35 seconds
ZEN 1 hours 24 minutes 9 seconds
XYZ 1 hours 33 minutes 23 seconds
ZEN 1 hours 11 minutes 38 seconds
XLS 0 hours 28 minutes 4 seconds
XYZ 0 hours 15 minutes 36 seconds
ZEN 0 hours 24 minutes 57 seconds
XLS 0 hours 46 minutes 44 seconds
EDIT
In order to find total amount of time spent by each script, this modified script should do the job:
#!/bin/bash
dtime=0
sname=""
namearr=()
timearr=()
while read line
do
_dtime=$(echo "$line" | awk '{print $1,$2,$3,$4}')
_sname=$(echo "$line" | awk '{print $10}')
_dtimesec=$(date +%s -d "$_dtime")
_timediff=$(( _dtimesec - dtime ))
_rc=1
for n in "${!namearr[#]}"
do
if [ "${namearr[$n]}" == "$_sname" ]; then
export _rc=$?
export ind=$n
break;
else
export _rc=1
fi
done
if [ $_rc -eq 0 ]; then
timearr[$ind]=$(( ${timearr[$ind]} + _timediff ))
else
if [ $dtime -eq 0 ] && [ "x$sname" == "x" ]; then
:
else
namearr+=($_sname)
timearr+=($_timediff)
fi
fi
dtime=$_dtimesec
sname=$_sname
done < test.txt
echo "Total time spent by each script:"
echo
for i in "${!namearr[#]}"
do
_gtime=${timearr[$i]}
printf "${namearr[$i]} %d hours %d minutes %d seconds\n" $(($_gtime/3600)) $(($_gtime%3600/60)) $(($_gtime%60))
done
Result:
$ ./test
Total time spent by each script:
XYZ 4 hours 44 minutes 44 seconds
ZEN 3 hours 28 minutes 34 seconds
XLS 1 hours 36 minutes 35 seconds
You can use the following gawk program:
time_spent.awk
BEGIN {
months["Jan"] = "01"
months["Feb"] = "02"
months["Mar"] = "03"
months["Apr"] = "04"
months["May"] = "05"
months["Jun"] = "06"
months["Jul"] = "07"
months["Aug"] = "08"
months["Seb"] = "09"
months["Oct"] = "10"
months["Nov"] = "11"
months["Dec"] = "12"
}
{
split($4, time, ":")
# mktime() manual: https://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html
now = mktime($6" "months[$2]" "$3" "time[1]" "time[2]" "time[3])
prv = $(NF-2)
cur = $(NF)
start[cur] = now
spent[prv]+=start[prv]?now-start[prv]:0
}
END {
for(i in spent) {
printf "%s seconds spent in %s\n", spent[i], i
}
}
Save it into a file time_spent.awk and execute it like this:
gawk -f time_spent.awk input.log
Output from the above example:
5795 seconds spent in XLS
0 seconds spent in abc
17084 seconds spent in XYZ
12514 seconds spent in ZEN
#!/usr/bin/env python
import sys
from time import strptime
from datetime import datetime
intervals = (
('weeks', 604800), # 60 * 60 * 24 * 7
('days', 86400), # 60 * 60 * 24
('hours', 3600), # 60 * 60
('minutes', 60),
('seconds', 1),
)
def display_time(seconds, granularity=2):
result = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
result.append("{} {}".format(value, name))
return ' '.join(result[:granularity])
with open(sys.argv[1], "rb") as df:
lines = df.readlines()
totals = {}
for i in range(len(lines)-1):
(_,t1,t2,t3,_,t4,_,_,_,_,_,scr) = lines[i].strip().split(' ')
st = datetime.strptime(' '.join([t1,t2,t3,t4]), "%b %d %H:%M:%S %Y")
(_,t1,t2,t3,_,t4,_,_,_,_,_,_) = lines[i+1].strip().split(' ')
et = datetime.strptime(' '.join([t1,t2,t3,t4]), "%b %d %H:%M:%S %Y")
if scr not in totals:
totals[scr] = 0
totals[scr] += (et-st).seconds
print("{} {}".format(scr,display_time((et-st).seconds, 3)))
print("\nTotals:")
for scr in totals:
print("{} {}".format(scr,display_time(totals[scr], 3)))
Here is the output, assuming your times are in a file named logfile:
$ ./times.py logfile
XYZ 2 hours 5 minutes 47 seconds
ZEN 1 hour 39 minutes 35 seconds
XYZ 1 hour 24 minutes 9 seconds
ZEN 1 hour 33 minutes 23 seconds
XLS 1 hour 11 minutes 38 seconds
XYZ 28 minutes 4 seconds
ZEN 15 minutes 36 seconds
XLS 24 minutes 57 seconds
XYZ 46 minutes 44 seconds
Totals:
XLS 1 hour 36 minutes 35 seconds
XYZ 4 hours 44 minutes 44 seconds
ZEN 3 hours 28 minutes 34 seconds
$
Note: I lifted the handy display_time function from here: Python function to convert seconds into minutes, hours, and days.
IE:
23 HL*3*2*23*0
24 PAT*19
25 NM1*QC*1*CUSTOMER*COLE
26 N3*228 PINEAPPLE CIRCLE
27 N4*CORA*PA*15108
28 DMG*D8*19940921*M
29 CLM*945405*5332.54***12>B>1*Y*A*Y*Y*P
30 HI*BK>2533
31 LX*1
32 SV1*HC>J2941*5332.54*UN*84***1
33 DTP*472*RD8*20110511-20110511
34 REF*6R*1099999731
35 NTE*ADD*GENERIC 12MG CARTRIDGE
36 LIN**N4*00013264681
37 CTP****7*UN
I want to populate column C with the text from row 29 as a min row with "945405" all the way to row 37 (the one with the text "CTP" in it). I cannot do this in VBA due to permissions. Is there a formula that will grab this value (it is always CLM * xxxxxx *...), assign it to column C using the "CLM" as the min row and CTP as the MAX row all the way through the SS? IE:
23 HL*3*2*23*0
24 PAT*19
25 NM1*QC*1*CUSTOMER*COLE
26 N3*228 PINEAPPLE CIRCLE
27 N4*CORA*PA*15108
28 DMG*D8*19940921*M
29 CLM*945405*5332.54***12>B>1*Y*A*Y*Y*P 945405
30 HI*BK>2533 945405
31 LX*1 945405
32 SV1*HC>J2941*5332.54*UN*84***1 945405
33 DTP*472*RD8*20110511-20110511 945405
34 REF*6R*1099999731 945405
35 NTE*ADD*GENERIC 12MG CARTRIDGE 945405
36 LIN**N4*00013264681 945405
37 CTP****7*UN 945405
38 NM1*DK*1*PATIENT*DEBORAH****XX*1
39 N3*123 MAIN ST*APT B
****Update*****
I was given permissions in VBA. How would I loop this?
Here is a clearer picture of what I am trying to accomplish
enter image description here
you can use the =MID(Source_Cell, Start_Position, Desired_Length) function to pull the substring. In your case it would be:
=MID(B29, 5, 6)
You can then put this formula in all of the cells you'd like it to be in.
I am using Perl v5.16.2
I am using the Net::SMPP modules and it returns me some data.
If I show this data, I get this (simplified) :
$VAR1 = bless( {
'receipted_message_id' => '400002F6E09C61701222120140',
'30' => '400002F6E09C61701222120140'
}, 'Net::SMPP::PDU' );
Now, let's assume this data is in $pdu and I do this :
$message_id = $pdu->{30}; # or $pdu->{receipted_message_id}, same result
myfunction($message_id);
Then, I have myfunction defined as :
sub myfunction {
my $message_id = shift;
my $message_id_static = '400002F6E09C61701222120140';
print Dumper($message_id);
print Dumper($message_id_static);
print hexdump($message_id);
print hexdump($message_id_static);
if ($message_id eq $message_id_static)
{
print "match\n";
}
else
{
print "no match\n";
}
}
The output of the program is :
$VAR1 = '400002F6E09C61701222120140';
$VAR1 = '400002F6E09C61701222120140';
Data::Hexdumper: data length isn't an integer multiple of lines
so has been padded with NULLs at the end.
0x0000 : 34 30 30 30 30 32 46 36 45 30 39 43 36 31 37 30 : 400002F6E09C6170
0x0010 : 31 32 32 32 31 32 30 31 34 30 00 00 00 00 00 00 : 1222120140......
Data::Hexdumper: data length isn't an integer multiple of lines
so has been padded with NULLs at the end.
0x0000 : 34 30 30 30 30 32 46 36 45 30 39 43 36 31 37 30 : 400002F6E09C6170
0x0010 : 31 32 32 32 31 32 30 31 34 30 00 00 00 00 00 00 : 1222120140......
no match
Which doesn't make any sense to me... !
If I try to use $message_id to do a SQLite query, it fails miserably. If I use $message_id_static instead, it works perfectly.
So, is this a weird internal Perl bug, or am I missing something ?
This has been driving me nuts for hours...
EDIT :
Using the perl debugger, I get this :
DB<3> x $message_id_static
0 '400002F6E09C61701222120140'
DB<4> x $message_id
0 "400002F6E09C61701222120140\c#"
So at least I see there is a difference in the strings, but why isn't it seen by the hexdump, and what is that \c# ?
Thanks !
The \c# character is Ctrl-#, which is the ASCII NUL character at code point zero
You can't see it in your hexdump output because it is indistinguishable from the 00 padding at the end of the dump
If you set $Data::Dumper::Useqq = 1 then it will be visible in the output from print Dumper $message_id
You can remove it from the variable by using s/\0\z// or tr/\0//d, but you should really investigate why it is there in the first place
I have a list of times which i want to add to a string
0900 1730
0900 1730
1000 1700
0930 1700
i need to break these up to hours and minutes like so
09 00 17 30
09 00 17 30
10 00 17 00
09 30 17 00
to do this i am using the MID() function to get the first two characters from the cell and then the last two. But when i do this for numbers that start with 0 of have 00 it drops the first 0 like so
0930 = ",MID(B2,1,2),",",MID(B2,3,2)," output - 93 0 what i want = 09 30
0900 = ",MID(B2,1,2),",",MID(B2,3,2)," output - 90 0 what i want = 09 00
1000 = ",MID(B2,1,2),",",MID(B2,3,2)," output - 10 0 what i want = 10 00
is there a way to solve this?
You can use a mid of a pre-formatted block:
=MID(RIGHT("0000"&B2,4),1,2) =MID(RIGHT("0000"&B2,4),3,2)
This should give you two strings like 09 & 30.
If you want two numeric values you can add a value function:
=VALUE(MID(RIGHT("0000"&B2,4),1,2))
One way is place Single Quote(') before the 0 then it will store the 0930 as text in cell
and your formula will also work, No need to change in the formula.
So the value 0930 will be '0930
I'd like to get a sequence of number like this 01,02,..,30
But if I use {01..30}, I will get 1,2,..30, the zero before single-digit number is missing.
How can I get the format like 01,02..30 ? Thanks in advance
In Bash4, your {01..30} brace expansion actually works as you want it to. If you are on Bash3 or lower you can use the printf builtin along with the brace expansion to get what you want without resorting to external commands.
$ printf "%02d " {1..20}
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
seq -w 1 30 # ought to work
as in:
for number in $(seq -w 1 30); do
touch /tmp/bleah$number.dat
done