Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

114
Views
Regex match hashtag with exceptions

I have the current expression:

/(?<![http://|https://|#])#([\d\w]+[^\d\s<]+[^\s<>]+)/g

However it's not compatible to run on Safari. I'm trying to handle the following cases:

#tag => match
#123 => no match
#32bit => match
##tag => no match
http://google.com/#/test => no match
tag##tag => no match
tag#tag => no match
<p>#tag</p> => match only #tag
#tag. => match only #tag
tag## => no match
tag# => no match
this is a match #tag => only #tag 

I wonder how I can make a character before the match result in a negative match. E.g. # and /.

Is there any alternative to negative look behind that is compatible with Safari?

Thanks in advance.

about 4 years ago · Santiago Trujillo
3 answers
Answer question

0

You might use a negated character class and a capture group, and make sure that there are not only digits.

Note that \w also matches \d

(?:^|[^\w#/])(#(?!\d+\b)\w+)\b

Explanation

  • (?: Non capture group
    • ^ Assert the start of the string
    • | Or
    • [^\w#/] Match a single non word char other than # or /
  • ) Close non capture group
  • ( Capture group 1
    • # Match literally
    • (?!\d+\b) Negative lookahead, assert not only digits to the right followed by a word boundary
    • \w+ Match 1+ word characters
  • ) Close group 1
  • \b A word boundary to prevent a partial word match

Regex demo

let regex = /(?:^|[^\w#/])(#(?!\d+\b)\w+)\b/;
[
  "#tag",
  "#123",
  "#32bit",
  "##tag",
  "http://google.com/#/test",
  "tag##tag",
  "tag#tag",
  "<p>#tag</p>",
  "#tag.",
  "tag##",
  "tag#"
].forEach(s => {
  const m = s.match(regex)
  if (m) {
    console.log(`${s} --> ${m[1]}`)
  }
})

Using the matches in a replacement:

let regex = /((?:^|[^\w#/]))(#(?!\d+\b)\w+)\b/;
[
  "#tag",
  "#123",
  "#32bit",
  "##tag",
  "http://google.com/#/test",
  "tag##tag",
  "tag#tag",
  "<p>#tag</p>",
  "#tag.",
  "tag##",
  "tag#",
  "this is a match #tag"
].forEach(s => {
  const m = s.match(regex)
  if (m) {
    console.log(s.replace(regex, "$1<span>$2</span>"))
  }
})

about 4 years ago · Santiago Trujillo Report

0

This satisfies your test cases. Not sure though whether you want this or not.

It does't work on #123 but I forgot it and I'm now lazy to add it as a screenshot.

/^(?:[^#]*[^#\w])?(#[\w]*[a-zA-Z][\w]*).*$/g

If you only want to allow <tags> before the "#", you can insted use @kendle's solution for the first non-capture group (before the actual group starting with #).

(?:<\w*>)?

enter image description here

about 4 years ago · Santiago Trujillo Report

0

If you use the following pattern the second matching group contains what you want.

^(<\w*>)?(#\w+[a-zA-Z])
about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!