Pick up particular lines from a text file and calculate them together - macos

This might be quite a long shot, but I've written an AppleScript for myself that keeps log on how long I work for whatever project. I'd like to create another script that calculates the overall spent time based on the info from a log file.
Generally my log files look like this:
140304 1353 - Start
140304 1459 - End
work time : 0106
break time : 0000
140307 1248 - Start
140307 1353 - End
work time : 0105
break time : 0000
140321 1101 - Start
140321 1306 - Have a break now
140321 1342 - Back to work
140321 1423 - Have a break now - Go eat
140321 1522 - Back to work
140321 1522 - End
work time : 0246
break time : 0135
So I would need to get every "work time" value and calculate them together.
I've tried googling around this, but I'm not sure how to get started.

Applescript's Text Item Delimiters (TIDs) are perfect for this. We just break the text up into a list by setting TIDs to the text just before the number you want to grab, in this case "work time". Then I just grab the next word after the TIDs because that's the number. So it's easy. The result of your example is 457. My script returns the sum plus shows all the values used to calculate the sum: {457, {"0106", "0105", "0246"}}
set workLog to "140304 1353 - Start
140304 1459 - End
work time : 0106
break time : 0000
140307 1248 - Start
140307 1353 - End
work time : 0105
break time : 0000
140321 1101 - Start
140321 1306 - Have a break now
140321 1342 - Back to work
140321 1423 - Have a break now - Go eat
140321 1522 - Back to work
140321 1522 - End
work time : 0246
break time : 0135"
set beforeText to "work time"
set AppleScript's text item delimiters to beforeText
set textItems to text items of workLog
set AppleScript's text item delimiters to ""
set theSum to 0
set sumItems to {}
repeat with i from 2 to count of textItems
set workTime to word 1 of (item i of textItems)
set end of sumItems to workTime
set theSum to theSum + (workTime as number)
end repeat
return {theSum, sumItems}
Now just replace the first line in my code with this and it will work for you on your log file. Good luck.
set workLog to read (choose file)

Here's a do shell script-based alternative to #regulus6633's pure AppleScript answer:
Note: I'm not sure what your work-time numbers such as 0106 represent - here I'm simply assuming that they are decimal integers to be summed.
set logFile to "/Users/jdoe/hours.log" # Replace with POSIX path to your log file
set total to do shell script ¬
"awk '/^work time :/ { total+=$4 } END { print total }' " ¬
& quoted form of logFile
The shell command uses awk, which greatly simplifies parsing.

Related

AppleScript Progress Bar with Reboot Button

I've recently been tasked with working on a project to switch antivirus software in the environment as we are changing to a new vendor. Naturally, this kind of effort will require a reboot on our endpoints once the old A/V software has been removed.
What I'm trying to do is create a reboot notification prompt for our Mac customers (since many are high up on the food chain) to let them know what we are doing.
This prompt will let them know they have 3 hours to reboot their Macs to complete the removal of the software if they are logged in. If they do not reboot within 3 hours, their workstation will automatically reboot.
Applescript has a great workflow that allows me to effectively communicate with our users, but I would like to change the Stop button to a reboot, so that our customers can reboot their Macs on demand.
I will work in logic later on to automatically reboot if they are not logged in.
I modified one of the scripts that I, "borrowed," from here
https://macscripter.net/viewtopic.php?id=46572
-- Progress Bar - Reboot Timer
progress_timer("03:00:00", "Reboot Timer") -- call the progress timer with an HMS time and timer label
return result
------------------------------------------
-- subroutines in alphabetical order --
------------------------------------------
-- getTimeConversion converts a time in HMS format (hh:mm:ss) to a time in seconds
on getTimeConversion(HMS_Time)
set HMSlist to the words of HMS_Time -- get {hh, mm, ss} from HMS time (p. 158 Rosenthal)
set theHours to item 1 of HMSlist
set theMinutes to item 2 of HMSlist
set theSeconds to item 3 of HMSlist
return round (theHours * (60 ^ 2) + theMinutes * 60 + theSeconds)
end getTimeConversion
-- progress_timer displays the elapsed time in a progress bar. For information on progress bars see: https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayProgress.html
on progress_timer(HMS_Time, timerLabel)
set theTimeSec to getTimeConversion(HMS_Time) -- convert the HMS format to seconds
set progress total steps to theTimeSec
set progress completed steps to 0
set startTime to (current date)
repeat with i from 0 to theTimeSec -- begin at i = 0 to start the timer at 00:00:00
set HMS_SoFar to TimetoText(i) -- convert the seconds so far to HMS format for display
set HMS_ToGo to TimetoText(theTimeSec - i) -- convert the seconds to go to HMS format for display
set progress completed steps to 0
set progress description to "
Your IT Department needs to make changes to your Mac.
Your workstation must be rebooted in order for these changes to take effect.
Your workstation will reboot in " & HMS_ToGo
set progress additional description to ¬
""
--"Time Elapsed: " & HMS_SoFar & return & ¬
--"Counting Down: " & HMS_ToGo
set progress completed steps to i
set elapsedTime to (current date) - startTime -- get actual elapsed time for adjusting delay
set lagAdjust to elapsedTime - i -- compute lag adjustment
delay 1 - lagAdjust -- delay 1 second minus any cumulative lag that needs removing
end repeat
--set HMS_Elapsed to TimetoText(elapsedTime) -- convert elapsedTime back to HMS format for display
set dialogText to null
--set dialogText to "Elapsed Time: " & return & ¬
-- "Nominal = " & HMS_Time & return & ¬
-- "Actual = " & HMS_Elapsed
tell me to activate
--display dialog dialogText with title timerLabel & " Timer"
return dialogText
end progress_timer
-- TimetoText converts a time in seconds to a time in HMS format (hh:mm:ss)
on TimetoText(theTime)
-- parameters - TheTime [integer]: the time in seconds
-- returns [text]: the time in the format hh:mm:ss
-- Nigel Garvey points out this script is only valid for parameter values up to 86399 seconds (23:59:59) and offers a solution for longer times here: https://macscripter.net/viewtopic.php?pid=134656#p134656
if (class of theTime) as text is "integer" then
set TimeString to 1000000 + 10000 * (theTime mod days div hours) -- hours
set TimeString to TimeString + 100 * (theTime mod hours div minutes) -- minutes
set TimeString to (TimeString + (theTime mod minutes)) as text -- seconds
tell TimeString to set theTime to (text -6 thru -5) & ":" & (text -4 thru -3) & ":" & (text -2 thru -1)
end if
return theTime
end TimetoText
Here's a screenshot of the resulting output.

trying to write an apple script that chimes every hour

I'm trying to write this script that chimes on every hour. I saved it as an application and selected the checkbox run after completion but it doesn't work. My code looks like this:
global chime
set chime to (path to resource "chime.mp3")
on idle
set currenthour to hours of (current date)
if currenthour = 0 then
set currenthour to 12
end if
if currenthour > 12 then
set currenthour to currenthour - 12
end if
set currentminute to minutes of (current date)
set currentsecond to seconds of (current date)
set currenttime to {currentminute, currentsecond} as text
if currenttime is "" then
repeat currenthour times
do shell script "afplay " & (quoted form of POSIX path of chime)
end repeat
end if
return 1
end idle
In a script app, the number you return from the on idle handler tells the system how long to sleep the app before the next idle invocation. You can use this set up a (loosely) accurate timer.
global chime, firstRun
on run
-- I'm not sure if this is necessary, but I always use explicit run handlers in script apps.
set chime to (path to resource "chime.mp3")
set firstRun to true
end run
on idle
set {currenthour, currentminute, currentsecond} to {hours, minutes, seconds} of (current date)
-- don't chime when the script app is activated
if not firstRun then
-- quick mathy way to retrieve the number of chimes.
set chimeCount to (currenthour + 11) mod 12 + 1
repeat chimeCount times
do shell script "afplay " & (quoted form of POSIX path of chime)
end repeat
else
set firstRun to true
end if
-- calculate the number of seconds until the next hour mark and tell app to sleep until then
return 60 * (60 - currentminute) + 60 - currentsecond
end idle

How to copy particular lines below particular text?

Suppose I have long text files output1, output2, and output3. In all output files, somewhere is "My Name is Rock (static)"
and below that text some values like
"My Name is Rock (static)"
10 20 30
-10 0.5 00
3.0 0.0 0.0 (different for all output file)
How can I copy the second column of the third line below the line ("My Name is Rock (static)") to a new file?
Remember line numbers are different for all output file.
awk 'c{c--;if(!c) print $2}/My Name is Rock \(static\)/{c=3}' ./output1 ./output2 ./output3
Explanation
/My Name is Rock \(static\)/{c=3}: When "My Name is Rock (static)" is seen, set c to 3
c{...}: If the counter c is non-zero, do ... (note, c starts off at 0)
c--;if(!c) print $2: Decrement counter, if counter is now zero, print 2nd field of current line

VBscript loop - Tell time every 15 minutes

I just want a file I can double-click and have Windows verbally tell me the time every 15 minutes. (Until I kill the process)
I found this tutorial for a VBscript that tells the time every hour, on the hour:
https://www.nextofwindows.com/windows-trick-how-to-make-your-computer-to-speak-out-time-at-every-hour
I couldn't get the Windows scheduler working with it for my purposes (start only when double-clicked and run every 15 minutes), and honestly, I just want a 15-minute-interval loop programmed into the script itself. (perhaps by using a Do/While loop and Sleep()?)
Another issue:
I tried adding a minutes variable so Windows would announce the minutes as well:
Dim speaks, speech
speaks = “It is ” & hour(time) & minute(time)
Set speech = CreateObject(“sapi.spvoice”)
speech.Speak speaks
However, it announces the time in an odd format this way. For example, It's currently 5:01AM, and when I run the script, Windows says "It is fifty-one." Why would it interpret 5:01 as fifty plus one? Earlier when I tested it at 4:32, it said "four hundred and thirty-two." I'd like it to just state the time in a normal 12-hour fashion.
This does 5 secs. So 60 x 15 = 900.
You need spaces between numbers if you want them parsed as individual numbers.
Set speech = CreateObject("sapi.spvoice")
Do
If Hour(Now) < 12 then
Var = Hour(Now) & " AM"
else
Var = Hour(Now) - 12 & " PM"
End If
speech.Speak Var & " and " & Minute(Now) & " minutes and " & Second(Now) & " seconds"
wscript.sleep 5
Loop

calculates the average value contained in a file for every 16 seconds

I have a big file "values.txt" in which there are a lot of values. These values ​​can be found in the file valeur.txt as follow :
File: "values.txt"
************************************************** *****************************************
2
14
18
20
23
.
.
.
24
******************************************************************************************
I want to write a script that calculate the average of values ​​read from the file values.txt for every 16 seconds
i e : After each 16 seconds I will calculate the average of values ​​that I have read in the file values.txt
for exmpl :
To read the file "value.txt", we will take (16 * 4 = 64) seconds.
So, when the exuction of script is finished, it must show 4 values. because every 16 seconds it will calculate an average.
I tried to do things but the concept of time (16 seconds) I still can't manage it
let "i=0"
let"cum=0"
while read var
do
if [timer] # how I could control the period of 16 seconde ?
then
let "i = i +1"
let "cum = cum + var"
else # 16 seconds have elapsed, so i calculate the averag
let "avrg_var= cum /i"
echo "$avrg_var">> new_file.txt
fi
done < values.txt
Thank you in advance for your answers and suggestions
Try this:
while :
do
let "i=0"
let "cum=0"
while read var
do
let "i = i +1"
let "cum = cum + var"
done < /tmp/values.txt
let "avrg_var= cum /i"
echo "$avrg_var">> new_file.txt
sleep 16
done
This doesn't work on a timer, just sleeps 16 seconds between runs.
Write a script that averages the values once, and then you can run your script with the watch command assuming your on a *nix based system. The default is 2 seconds but you can change it to what ever you want and it will repeatedly run in the terminal until canceled

Resources