If..Then..Else With Exact (Case Sensitive) String Matches

I wanted to do a comparison of 2 strings and make sure they were an exact (case sensitive) match. Most of the string comparisons available in the If...Then...Else action are case insensitive. I came up with 2 solutions to the problem (mostly because i didn't find the Encode for Regular Expression filter until after method 2 was found).

Solution 1:

Regular expressions are case sensitive by default (there is a flag you can add to make them case insensitive). Generally a regex will search a string to see if it contains the pattern. However that means having extra stuff before or after the pattern is OK. You can prevent this by using the anchors ^ (start of string) and $ (end of string) around your pattern. Now the search string must only contain the pattern.

The next problem that arises is if your pattern contains regex special characters like + or () or []. These can cause a string that doesn't match to match. For example the string ABCDE will match the pattern A+(BC)DE.

To fix this you can use the Filter Action and Filter the string you'll use in the pattern as "Encode for Regular Expression". This will mark all the special characters so they are matched exactly. For example the filter will turn my example above into:
A\x2B\x28BC\x29DE.

You can disable the Filter action to see that the two strings will match without the filter.

Solution 2:

I came up with this solution before I found the Filter action to fix my RegEx problem in solution 1. It uses the case sensitive matching available in the Search and Replace action. If an exact match of the string is found, it replaces it with the word MATCH. The if then else then does an "is" comparison against just "MATCH". So if the original string contains the search string plus extra, the final string will be MATCH plus the extra and the if...then...else fails.

Macros:

[KvanH KM Discourse Macros] Exact String Match Macros.kmmacros (8.5 KB)

I don't quite follow your context sorry, but have you realised that the logic in an If action has a couple of possibilities?

The Contains logic is a string match, but the Matches logic uses regex by default. It should possibly say "Matches (using regex)" but I digress.

I think this means that in solution 1, the second and third actions are unnecessary - you could just put the "A+(BC)DE" expression into the "matches" text entry field of the fourth action.

  1. I'm not trying to match against a pattern, I'm just using the case sensitivity of regex. In my example the result should be No Match. I want an exact match. The A+(BC)DE is not a pattern, it's a plain string but it is being interperted as a pattern. I use the Filter to disable that. Getting a result of Match between ABCDE and A+(BC)DE is wrong for me. If you run your example the result will be Match.

  2. The intent is that the 2 strings can come from anywhere (my personal need is 2 clipboards, but it could be 2 variables or 2 subroutine parameters). I put the values directly in clipboards in my example to demonstrate the issue, this was pulled from my actual usage to simplify the example. My actual macro actually has something on the system clipboard and I want to compare that against whatever is currently selected and I want to know if they are an exact match. What I copied and what I selected are arbritrary and therefore need to be in clipboards (or variables).

Hey Kevin,

I think this is what you're trying to accomplish.

I'm not fiddling with the regex metacharacter filter, but I am switching on case-sensitive matching.

You also have to manage the beginning and end of the match, otherwise your test pattern acts as contains.

-Chris


Match with Case-Sensitive v1.00.kmmacros (8.4 KB)

Macro-Image

Keyboard Maestro Export

1 Like

Just realized my screenshot above doesn't include my final working solution which is similar to yours, however yours also doesn't do what I want.

My problem: Compare 2 ARBITRARY strings. You are comparing one arbitrary string to one hardcoded pattern.

If I just change yours to compare 2 strings, it works for your example

Macro Image - 1 - Modified example, apparently working

However, since the 2 strings I'm testing could be anything, String2 could be a string that includes regular expression characters. So if I add a + to the middle of String2, your example will now fail, it returns true even though FORK! and FO+RK! are not the same string.

Macro Image - 2 - Fail Example

To make it work for any string, filter String2 so any regular expression special characters are encoded into it's hexadecimal character (plus becomes \x2B, exclamation mark becomes \x21, etc...). Now it'll always work.

Macro Image - 3 - Final Working

Macros:
String Match Macros.kmmacros (25.9 KB)

Hi Chris,

What does (?-i) mean?

Cheers,

Hans

It means switch case-insensitive off.

Just as (?i) means switch case-insensitive on.

See the PCRE modifiers here:

Regular Expressions Tutorial - Regex modifiers (flags)

Follow up with the ICU (KM) syntax, which is not identical to PCRE:

1 Like