tailNum=$KMVAR_last_engine_log_lines
if [[ $tailNum =~ ^[0-9]+$ && $tailNum -gt 0 ]]; then
grepString=$KMVAR_grepString
kmEngineLog=~/'Library/Logs/Keyboard Maestro/Engine.log'
tail -n $tailNum "$kmEngineLog" \
| awk -v g="$grepString" '/Execute macro/ && $0 ~ g {gsub(/.*β|β.*/, "", $0); print $0}' \
| tail -1
else
echo "Invalid value for \$tailNum: $tailNum"
fi
This modification changes a few things.
- Changes from
sed to awk for text manipulation because sed has issues processing the smart quotes that are used in the lines of the KM log that I was working with. Specifically:
Execute macro βGoogle sheets - Insert rows belowβ from trigger Name
- (
" vs β)
- RegEx looks for line endings matching
grepString2 (KMVariable) and returns what is inside the smart quotes.
- Uses
$KMVAR_grepString instead of $KMVAR_local__grepString and other non-localized variables so that I can pass values to this macro as a subroutine.
- Adds minimal validation and logging.
Explanation:
I'm pretty new to this stuff and stumbled through it with a lot of back and forth with ChatGPT. In case others in a similar situation come here I'll post what I understand (mostly from ChatGPT) below. Corrections and clarifications are welcome.
- The value of
$KMVAR_last_engine_log_lines is stored in a variable called $tailNum.
- The
if statement checks if $tailNum is a positive integer. If it is, the script continues with the rest of the code. If it's not, an error message is displayed indicating that $tailNum is invalid.
- If
$tailNum is valid, the value of $KMVAR_grepString is stored in a variable called $grepString.
- The path to the Keyboard Maestro engine log is stored in a variable called
kmEngineLog.
- The
tail command is used to extract the last $tailNum lines from the kmEngineLog file.
- The output of the
tail command is piped to the awk command, which filters only the lines that contain the string "Execute macro" and match the search pattern stored in $grepString.
- The
gsub function is used to remove everything before the first occurrence of β and everything after the last occurrence of β. The resulting string contains only the macro name.
- The
print function is used to print the macro name to the output.
- The output of the
awk command is piped to the second tail command, which returns only the last occurrence of the extracted macro name.
So the updated script essentially extracts the last $tailNum lines from the Keyboard Maestro engine log, filters only the lines that contain the string "Execute macro" and match the search pattern stored in $KMVAR_grepString2, and extracts the macro name from the filtered lines.
sed and awk are pretty cool.
Here is the explanation for the awk line.
awk -v g="$grepString" '/Execute macro/ && $0 ~ g {gsub(/.*β|β.*/, "", $0); print $0}'
- The
awk command is prefixed by a | pipe which connects the output of one command to the input of another command. In this case, it's going from tail to awk and back to tail
- This
awk command has two parts separated by &&:
-
/Execute macro/: This is a pattern that matches lines that contain the string "Execute macro".
-
$0 ~ g: This is a pattern that matches lines that contain the search pattern stored in the $grepString variable. The -v option is used to pass the value of $grepString to the awk command.
- By using
&& to combine these two patterns, the awk command filters only the lines that contain the string "Execute macro" and that match the search pattern stored in $grepString.
- The filtered lines are then processed by the action in braces
{}:
-
gsub(/.*β|β.*/, "", $0): This function removes everything before the first occurrence of β and everything after the last occurrence of β in the line.
-
print $0: This function prints the resulting line to the output.
- So the
awk command essentially extracts the macro name from the lines that match the pattern /Execute macro/ && $0 ~ g, where g is the search pattern stored in $grepString. The resulting macro name is then printed to the output.
sed and smart quotes
The issue with using "smart quotes" or "curly quotes" in the sed command is that the character used to surround the string in the regular expression is not recognized by sed as a valid delimiter. This can cause sed to interpret the regular expression incorrectly or not at all, resulting in unexpected behavior or errors.
For example, when using smart quotes in the sed command, the regular expression may not match any lines in the input, even if there are lines that should match. This is because sed is treating the smart quotes as literal characters in the regular expression, rather than as delimiters.
In general, it's best to use standard ASCII characters for delimiters in sed commands to avoid any potential issues with character encoding or interpretation.