Regular Expressions 101

Save & Share

Flavor

  • PCRE2 (PHP >=7.3)
  • PCRE (PHP <7.3)
  • ECMAScript (JavaScript)
  • Python
  • Golang
  • Java 8
  • .NET 7.0 (C#)
  • Rust
  • Regex Flavor Guide

Function

  • Match
  • Substitution
  • List
  • Unit Tests

Tools

Sponsors
There are currently no sponsors. Become a sponsor today!
An explanation of your regex will be automatically generated as you type.
Detailed match information will be displayed here automatically.
  • All Tokens
  • Common Tokens
  • General Tokens
  • Anchors
  • Meta Sequences
  • Quantifiers
  • Group Constructs
  • Character Classes
  • Flags/Modifiers
  • Substitution
  • A single character of: a, b or c
    [abc]
  • A character except: a, b or c
    [^abc]
  • A character in the range: a-z
    [a-z]
  • A character not in the range: a-z
    [^a-z]
  • A character in the range: a-z or A-Z
    [a-zA-Z]
  • Any single character
    .
  • Alternate - match either a or b
    a|b
  • Any whitespace character
    \s
  • Any non-whitespace character
    \S
  • Any digit
    \d
  • Any non-digit
    \D
  • Any word character
    \w
  • Any non-word character
    \W
  • Match everything enclosed
    (?:...)
  • Capture everything enclosed
    (...)
  • Zero or one of a
    a?
  • Zero or more of a
    a*
  • One or more of a
    a+
  • Exactly 3 of a
    a{3}
  • 3 or more of a
    a{3,}
  • Between 3 and 6 of a
    a{3,6}
  • Start of string
    ^
  • End of string
    $
  • A word boundary
    \b
  • Non-word boundary
    \B

Regular Expression
No Match

/
/
gm

Test String

Code Generator

Generated Code

re = /(?=(?:^(?:\d\d\d\d-(?:0[1-9]|10|11|12)-(?:0[1-9]|1[0-9]|2[0-8])|\d\d\d\d-(?:0[13-9]|10|11|12)-(?:29|30)|\d\d\d\d-(?:0[13578]|10|12)-31|(?:\d\d[2468][048]|\d\d0[48]|\d\d[13579][26])-02-29|(?:[02468][048]00|[13579][26]00)-02-29)T(?:(?:0[0-9]|1[0-9]|2[0-3]):(?:[0-5][0-9]):(?:[0-5][0-9]))(?:\.\d\d\d)?(?:Z|[\+\-](?:0[0-9]|1[012]):00|\+0[34569]:30|\+10:30|-0[39]:30|\+1[34]:00|\+0[58]:45|\+12:45)$)|^(?:1972|198[1235]|199[2347]|2012|2015)-06-30T23:59:60Z$|^(?:197[2-9]|1987|1989|199[058]|2005|2008|2016)-12-31T23:59:60Z$)(?!.*-00:00$)^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.(\d\d\d))?((Z)|([\+\-])(\d\d):(\d\d))$/m str = 'Strong Matcher for ISO 8601 / RFC 3339 Date Times; rejects bad TZ offsets, illegal times (Museum of Bad Data) See below for expanded matcher ``` // accept: Exemplars 2008-02-03T04:05:06.007Z 2008-02-03T04:05:06Z 0000-01-01T00:00:00.000Z 0000-02-29T04:05:06.007Z 9999-12-31T23:59:59.999Z 9999-12-31T23:59:59Z 2008-02-03T04:05:06.007+12:45 2008-02-03T04:05:06+03:30 0000-01-01T00:00:00.007-09:30 0000-02-29T04:05:06.007+14:00 9999-12-31T23:59:59.999+12:00 9999-12-31T23:59:59-12:00 // accept: Leap day, year is multiple of four 0004-02-29T04:05:06.007Z 0008-02-29T04:05:06.007Z 0012-02-29T04:05:06.007Z 0016-02-29T04:05:06.007Z 0020-02-29T04:05:06.007Z 0024-02-29T04:05:06.007Z 0028-02-29T04:05:06.007Z 0032-02-29T04:05:06.007Z 0036-02-29T04:05:06.007Z 0040-02-29T04:05:06.007Z 0044-02-29T04:05:06.007Z 0048-02-29T04:05:06.007Z 0052-02-29T04:05:06.007Z 0056-02-29T04:05:06.007Z 0060-02-29T04:05:06.007Z 0064-02-29T04:05:06.007Z 0068-02-29T04:05:06.007Z 0072-02-29T04:05:06.007Z 0076-02-29T04:05:06.007Z 0080-02-29T04:05:06.007Z 0084-02-29T04:05:06.007Z 0088-02-29T04:05:06.007Z 0092-02-29T04:05:06.007Z 0096-02-29T04:05:06.007Z 1560-02-29T04:05:06.007Z 2004-02-29T04:05:06.007Z 2008-02-29T04:05:06.007Z 2012-02-29T04:05:06.007Z 2016-02-29T04:05:06.007Z 2020-02-29T04:05:06.007Z 2024-02-29T04:05:06.007Z 2028-02-29T04:05:06.007Z 2032-02-29T04:05:06.007Z 2036-02-29T04:05:06.007Z 2040-02-29T04:05:06.007Z 2044-02-29T04:05:06.007Z 9996-02-29T04:05:06.007Z // accept: Leap day, year is Multiple of 400 0000-02-29T04:05:06.007Z 0400-02-29T04:05:06.007Z 0800-02-29T04:05:06.007Z 1200-02-29T04:05:06.007Z 1600-02-29T04:05:06.007Z 2000-02-29T04:05:06.007Z 2400-02-29T04:05:06.007Z 2800-02-29T04:05:06.007Z 3200-02-29T04:05:06.007Z 3600-02-29T04:05:06.007Z 4000-02-29T04:05:06.007Z 4400-02-29T04:05:06.007Z 4800-02-29T04:05:06.007Z 5200-02-29T04:05:06.007Z 5600-02-29T04:05:06.007Z 6000-02-29T04:05:06.007Z 6400-02-29T04:05:06.007Z 6800-02-29T04:05:06.007Z 7200-02-29T04:05:06.007Z 7600-02-29T04:05:06.007Z 8000-02-29T04:05:06.007Z 8400-02-29T04:05:06.007Z 8800-02-29T04:05:06.007Z 9200-02-29T04:05:06.007Z 9600-02-29T04:05:06.007Z // accept: Day in range for month 2008-01-30T04:05:06.007Z 2008-03-30T04:05:06.007Z 2008-04-30T04:05:06.007Z 2008-05-30T04:05:06.007Z 2008-06-30T04:05:06.007Z 2008-07-30T04:05:06.007Z 2008-08-30T04:05:06.007Z 2008-09-30T04:05:06.007Z 2008-10-30T04:05:06.007Z 2008-11-30T04:05:06.007Z 2008-12-30T04:05:06.007Z 2008-01-31T04:05:06.007Z 2008-03-31T04:05:06.007Z 2008-05-31T04:05:06.007Z 2008-07-31T04:05:06.007Z 2008-08-31T04:05:06.007Z 2008-10-31T04:05:06.007Z 2008-12-31T04:05:06.007Z // accept: had leap second 1972-06-30T23:59:60Z 1981-06-30T23:59:60Z 1982-06-30T23:59:60Z 1983-06-30T23:59:60Z 1985-06-30T23:59:60Z 1992-06-30T23:59:60Z 1993-06-30T23:59:60Z 1994-06-30T23:59:60Z 1997-06-30T23:59:60Z 2012-06-30T23:59:60Z 2015-06-30T23:59:60Z 1972-12-31T23:59:60Z 1973-12-31T23:59:60Z 1974-12-31T23:59:60Z 1975-12-31T23:59:60Z 1976-12-31T23:59:60Z 1977-12-31T23:59:60Z 1978-12-31T23:59:60Z 1979-12-31T23:59:60Z 1987-12-31T23:59:60Z 1989-12-31T23:59:60Z 1990-12-31T23:59:60Z 1995-12-31T23:59:60Z 1998-12-31T23:59:60Z 2005-12-31T23:59:60Z 2008-12-31T23:59:60Z 2016-12-31T23:59:60Z // REJECT: Year out of range 10000-02-29T04:05:06.007Z // REJECT: Month out of range 2008-00-30T04:05:06.007Z 2008-13-30T04:05:06.007Z 2008-14-30T04:05:06.007Z 2008-20-30T04:05:06.007Z // REJECT: Day out of range for month 2008-02-30T04:05:06.007Z 2008-04-31T04:05:06.007Z 2008-06-31T04:05:06.007Z 2008-09-31T04:05:06.007Z 2008-11-31T04:05:06.007Z 2008-02-31T04:05:06.007Z // REJECT: Day out of range 2008-12-32T04:05:06.007Z 2008-12-99T04:05:06.007Z 2008-12-00T04:05:06.007Z // REJECT: Hour out of range 2008-12-08T60:05:06.007Z 2008-12-08T99:05:06.007Z // REJECT: Minute out of range 2008-12-08T04:60:06.007Z 2008-12-08T04:99:06.007Z // REJECT: Seconds out of range 9999-12-31T59:59:61.999Z 2008-02-03T04:05:61.999Z 2008-02-03T04:05:61Z // REJECT: Negative dates not accepted -2000-02-29T04:05:06.007Z -0400-02-29T04:05:06.007Z -0100-02-29T04:05:06.007Z -0004-02-29T04:05:06.007Z // REJECT: stray characters 2008-12-31T04:05:06.007Z 2008-12-31T04:05:06.007Z 2008-12-31T04:05:06.007 Z // REJECT: Malformed 2008-02-0304:05:06.007Z 20080203T040506.007Z 2008-02-03T04:05:06007Z 2008-02-03T04:05:06.7Z 2008-02-03T04:05:06.07Z 2008-02-03T04:05:06.0007Z 2008-02-03T04:05:06 2008-02-03T04:05:06.Z // REJECT: no leap second 1973-06-30T23:59:60Z 1974-06-30T23:59:60Z 1975-06-30T23:59:60Z 1976-06-30T23:59:60Z 1977-06-30T23:59:60Z 1978-06-30T23:59:60Z 1979-06-30T23:59:60Z 1980-06-30T23:59:60Z 1984-06-30T23:59:60Z 1986-06-30T23:59:60Z 1987-06-30T23:59:60Z 1988-06-30T23:59:60Z 1989-06-30T23:59:60Z 1990-06-30T23:59:60Z 1991-06-30T23:59:60Z 1995-06-30T23:59:60Z 1996-06-30T23:59:60Z 1998-06-30T23:59:60Z 1999-06-30T23:59:60Z 2000-06-30T23:59:60Z 2001-06-30T23:59:60Z 2002-06-30T23:59:60Z 2003-06-30T23:59:60Z 2004-06-30T23:59:60Z 2005-06-30T23:59:60Z 2006-06-30T23:59:60Z 2007-06-30T23:59:60Z 2008-06-30T23:59:60Z 2009-06-30T23:59:60Z 2010-06-30T23:59:60Z 2011-06-30T23:59:60Z 2013-06-30T23:59:60Z 2014-06-30T23:59:60Z 2016-06-30T23:59:60Z 2017-06-30T23:59:60Z 2018-06-30T23:59:60Z 2019-06-30T23:59:60Z 2020-06-30T23:59:60Z 2021-06-30T23:59:60Z 2022-06-30T23:59:60Z 2023-06-30T23:59:60Z 1980-12-31T23:59:60Z 1981-12-31T23:59:60Z 1982-12-31T23:59:60Z 1983-12-31T23:59:60Z 1984-12-31T23:59:60Z 1985-12-31T23:59:60Z 1986-12-31T23:59:60Z 1988-12-31T23:59:60Z 1991-12-31T23:59:60Z 1992-12-31T23:59:60Z 1993-12-31T23:59:60Z 1994-12-31T23:59:60Z 1996-12-31T23:59:60Z 1997-12-31T23:59:60Z 1999-12-31T23:59:60Z 2000-12-31T23:59:60Z 2001-12-31T23:59:60Z 2002-12-31T23:59:60Z 2003-12-31T23:59:60Z 2004-12-31T23:59:60Z 2006-12-31T23:59:60Z 2007-12-31T23:59:60Z 2009-12-31T23:59:60Z 2010-12-31T23:59:60Z 2011-12-31T23:59:60Z 2012-12-31T23:59:60Z 2013-12-31T23:59:60Z 2014-12-31T23:59:60Z 2015-12-31T23:59:60Z 2017-12-31T23:59:60Z 2018-12-31T23:59:60Z 2019-12-31T23:59:60Z 2020-12-31T23:59:60Z 2021-12-31T23:59:60Z 2022-12-31T23:59:60Z 2023-12-31T23:59:60Z // REJECT: assumes no future leap seconds 2024-12-31T23:59:60Z 2099-12-31T23:59:60Z 9999-12-31T23:59:60Z // REJECT: leap seconds only in UTC format 2005-12-31T23:59:60+00:00 2008-12-31T23:59:60+00:00 // REJECT: Not a leap day, year is not a multiple of four 0101-02-29T04:05:06.007Z 0102-02-29T04:05:06.007Z 0103-02-29T04:05:06.007Z 1537-02-29T04:05:06.007Z 1538-02-29T04:05:06.007Z 2001-02-29T04:05:06.007Z 2002-02-29T04:05:06.007Z 2003-02-29T04:05:06.007Z 2021-02-29T04:05:06.007Z 2022-02-29T04:05:06.007Z 2023-02-29T04:05:06.007Z 2025-02-29T04:05:06.007Z 2026-02-29T04:05:06.007Z 2027-02-29T04:05:06.007Z 2029-02-29T04:05:06.007Z 2030-02-29T04:05:06.007Z 2031-02-29T04:05:06.007Z 2033-02-29T04:05:06.007Z 2034-02-29T04:05:06.007Z 2035-02-29T04:05:06.007Z 2037-02-29T04:05:06.007Z 2038-02-29T04:05:06.007Z 2039-02-29T04:05:06.007Z 2041-02-29T04:05:06.007Z 2042-02-29T04:05:06.007Z 2043-02-29T04:05:06.007Z 9997-02-29T04:05:06.007Z 9998-02-29T04:05:06.007Z 9999-02-29T04:05:06.007Z // REJECT: Not a leap day, year is a multiple of 100 but not 400 0100-02-29T04:05:06.007Z 0200-02-29T04:05:06.007Z 0300-02-29T04:05:06.007Z 0500-02-29T04:05:06.007Z 0600-02-29T04:05:06.007Z 0700-02-29T04:05:06.007Z 0900-02-29T04:05:06.007Z 1000-02-29T04:05:06.007Z 1100-02-29T04:05:06.007Z 1500-02-29T04:05:06.007Z 2100-02-29T04:05:06.007Z 2200-02-29T04:05:06.007Z 2300-02-29T04:05:06.007Z 2500-02-29T04:05:06.007Z 2600-02-29T04:05:06.007Z 2700-02-29T04:05:06.007Z 2900-02-29T04:05:06.007Z 3000-02-29T04:05:06.007Z 3100-02-29T04:05:06.007Z 3300-02-29T04:05:06.007Z 3400-02-29T04:05:06.007Z 3500-02-29T04:05:06.007Z 3700-02-29T04:05:06.007Z ``` ``` (?= (?:^ (?: # All non-leap-second YYYY-MM-DD parts: (?:\\d\\d\\d\\d-(?:0[1-9] |10|11|12)-(?:0[1-9]|1[0-9]|2[0-8])) # Days 01-28 | (?:\\d\\d\\d\\d-(?:0[13-9] |10|11|12)-(29|30)) # Days 29+30 | (?:\\d\\d\\d\\d-(?:0[13578]|10 |12)-31) # Day 31 | (?:\\d\\d[2468][048]|\\d\\d0[48]|\\d\\d[13579][26])-02-29 # leap years not divisible by 100 | (?:[02468][048]00|[13579][26]00)-02-29 # leap years divisible by 400 ) T (?:(?:0[0-9]|1[0-9]|2[0-3]):(?:[0-5][0-9]):(?:[0-5][0-9])) # time part (?:\\.\\d\\d\\d)? # ms part (optional) (?:Z|[\\+\\-](?:0[0-9]|1[012]):00|\\+0[34569]:30|\\+10:30|-0[39]:30|\\+1[34]:00|\\+0[58]:45|\\+12:45) $) |^(?:1972 |198[1235]|199[2347]|2012|2015 )-06-30T23:59:60Z$ # all june leapsecs |^(?:197[2-9]|1987|1989|199[058] |2005|2008|2016)-12-31T23:59:60Z$ # all december leapsecs ) (?!.*-00:00$) # if given a -00:00 offset reject unconditionally, psychhhh # OK! Since only valid times are now possible, we can use a loose pattern match to parse. ^(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d):(\\d\\d)(?:\\.(\\d\\d\\d))?((Z)|([\\+\\-])(\\d\\d):(\\d\\d))$ ```' # Print the match result str.scan(re) do |match| puts match.to_s end

Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Ruby, please visit: http://ruby-doc.org/core-2.2.0/Regexp.html