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.