Home > OS >  Regex behaves different for mobile [on iOS] and desktop
Regex behaves different for mobile [on iOS] and desktop

Time:09-06

I know it sounds strange, but for some reason my regex works very good for desktop, but when it comes to mobile it doesn't recognize the pattern on iOS only.

The idea is the capture the following patterns:

  • Name 0:02
  • Name 0:02:00
  • [ Name: 0:03 ]
  • [ Name: 0:03:00 ]

Here's my regex:

/(^\s*)?(\[?)(\d{1,2}:\d{1,2})(:\d{1,2})?(\.\d*)?(\]?\s*)/

This is how I use it

const App = () => {
  const text = "Welcome 0:00"
  const result = text.match(
    /(^\s*)?(\[?)(\d{1,2}:\d{1,2})(:\d{1,2})?(\.\d*)?(\]?\s*)/,
  );
  return(
    <div className="box">
      <h1>{result}</h1>  
    </div>
  );
}

You can even see the results in the codepen link:

https://codepen.io/or-nakash/pen/WNJbKKK

If you use desktop you'll see the result, but if you enter this link from mobile you will see it's empty (because it's null).

Do you have any idea what could have caused this?

CodePudding user response:

Oh you know what, It's probably that trailing comma:

  const result = text.match(
    /(^\s*)?(\[?)(\d{1,2}:\d{1,2})(:\d{1,2})?(\.\d*)?(\]?\s*)/,
//  ----------------------------------------------------------^
  );

Some browsers don't like this.

CodePudding user response:

The main problem is that match returns an array of all groups, and you pass the full array to the template - that's why the result is incorrect and the hour is printed twice:

const text = "Welcome 0:00"
const result = text.match(
    /(^\s*)?(\[?)(\d{1,2}:\d{1,2})(:\d{1,2})?(\.\d*)?(\]?\s*)/,
);
// result is ["0:00", undefined, "", "0:00", undefined, undefined, ""]

You want to use the first element in the array ({result[0]}), which is the full match (or a specific group, but this pattern doesn't have a group for the hour only). The rest of the elements are the captured groups (every (...) will add an element).

You can try capturing the hour only, this can simplify the pattern:

/\d{1,2}:\d{1,2}(?:\d{1,2})?(?:\.\d )?/

I used non-capturing groups (?:...) because that's better when we don't need to extract and use the captured value.
The optional groups for spaces and brackets in the original pattern don't add much anyway (for example, it doesn't try to capture "Name").

As for the null - this looks like a bug in Safari! Safari doesn't like it what you have an optional ^ - my guess is that this is an optimization gone wrong:

console.log("a 1".match(/(^)?\d/));

  • Related