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
  • Non-capturing group
    (?:...)
  • Capturing group
    (...)
  • 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

r"
"
gm

Test String

Substitution

Processing...

Code Generator

Generated Code

# coding=utf8 # the above tag defines encoding for this document and is for Python 2.x compatibility import re regex = r"^(/\*)(\n)(\*)(.*?)(\n)(\*/$)|(?<!:)(//)(.*?)$" test_str = ("// intraday.gs -- Supports downloading intraday (minute-by-minute) step data\n" "// Will not work without special permission from Fitbit\n\n" "// Simon Bromberg (http://sbromberg.com)\n" "// You are free to use, modify, copy any of the code in this script for your own purposes, as long as it's not for evil\n" "// If you do anything cool with it, let me know!\n" "// Note: there are minor improvements/cleanups still to be made in this file, but it should work as is if everything is setup properly\n" "// See readme on github repo for more information\n\n" "// Script based on post here http://quantifiedself.com/2014/09/download-minute-fitbit-data/ by Ernesto Ramirez\n" "/*\n" "* Do not change these key names. These are just keys to access these properties once you set them up by running the Setup function from the Fitbit menu\n" "*/\n" "// Key of ScriptProperty for Firtbit consumer key.\n" "var CONSUMER_KEY_PROPERTY_NAME = \"fitbitConsumerKey\";\n" "// Key of ScriptProperty for Fitbit consumer secret.\n" "var CONSUMER_SECRET_PROPERTY_NAME = \"fitbitConsumerSecret\";\n\n" "var SERVICE_IDENTIFIER = 'fitbit';\n\n" "function onOpen() {\n" " var ss = SpreadsheetApp.getActiveSpreadsheet();\n" " var menuEntries = [\n" " {\n" " name: \"Setup\",\n" " functionName: \"setup\"\n" " },\n" " {\n" " name: \"Authorize\",\n" " functionName: \"showSidebar\"\n" " },\n" " {\n" " name: \"Reset\",\n" " functionName: \"clearService\"\n" " },\n" " {\n" " name: \"Download data\",\n" " functionName: \"refreshTimeSeries\"\n" " }];\n" " ss.addMenu(\"Fitbit\", menuEntries);\n" "}\n\n\n" "function isConfigured() {\n" " return getConsumerKey() != \"\" && getConsumerSecret() != \"\";\n" "}\n\n" "function setConsumerKey(key) {\n" " ScriptProperties.setProperty(CONSUMER_KEY_PROPERTY_NAME, key);\n" "}\n\n" "function getConsumerKey() {\n" " var key = ScriptProperties.getProperty(CONSUMER_KEY_PROPERTY_NAME);\n" " if (key == null) {\n" " key = \"\";\n" " }\n" " return key;\n" "}\n\n" "function setLoggables(loggable) {\n" " ScriptProperties.setProperty(\"loggables\", loggable);\n" "}\n\n" "function getLoggables() {\n" " var loggable = ScriptProperties.getProperty(\"loggables\");\n" " if (loggable == null) {\n" " loggable = LOGGABLES;\n" " } else {\n" " loggable = loggable.split(',');\n" " }\n" " return loggable;\n" "}\n\n" "function setConsumerSecret(secret) {\n" " ScriptProperties.setProperty(CONSUMER_SECRET_PROPERTY_NAME, secret);\n" "}\n\n" "function getConsumerSecret() {\n" " var secret = ScriptProperties.getProperty(CONSUMER_SECRET_PROPERTY_NAME);\n" " if (secret == null) {\n" " secret = \"\";\n" " }\n" " return secret;\n" "}\n\n" "// function saveSetup saves the setup params from the UI\n" "function saveSetup(e) {\n" " setConsumerKey(e.parameter.consumerKey);\n" " setConsumerSecret(e.parameter.consumerSecret);\n" " setLoggables(e.parameter.loggables);\n" " setFirstDate(e.parameter.firstDate);\n" " setLastDate(e.parameter.lastDate);\n" " var app = UiApp.getActiveApplication();\n" " app.close();\n" " return app;\n" "}\n\n" "function setFirstDate(firstDate) {\n" " ScriptProperties.setProperty(\"firstDate\", firstDate);\n" "}\n\n" "function getFirstDate() {\n" " var firstDate = ScriptProperties.getProperty(\"firstDate\");\n" " if (firstDate == null) {\n" " firstDate = \"2012-01-01\";\n" " }\n" " return firstDate;\n" "}\n\n" "function setLastDate(lastDate) {\n" " ScriptProperties.setProperty(\"lastDate\", lastDate);\n" "}\n\n" "function getLastDate() {\n" " var lastDate = ScriptProperties.getProperty(\"lastDate\");\n" " if (lastDate == null) {\n" " var today = new Date();\n" " lastDate = Utilities.formatDate(new Date(), SpreadsheetApp.getActive().getSpreadsheetTimeZone(),\"yyyy-mm-dd\");\n" " }\n" " return lastDate;\n" "}\n\n" "// function setup accepts and stores the Consumer Key, Consumer Secret, Project Key, firstDate, and list of Data Elements\n" "function setup() {\n" " var doc = SpreadsheetApp.getActiveSpreadsheet();\n" " var app = UiApp.createApplication().setTitle(\"Setup Fitbit Download\");\n" " app.setStyleAttribute(\"padding\", \"10px\");\n\n" " var consumerKeyLabel = app.createLabel(\"Fitbit OAuth 2.0 Client ID:*\");\n" " var consumerKey = app.createTextBox();\n" " consumerKey.setName(\"consumerKey\");\n" " consumerKey.setWidth(\"100%\");\n" " consumerKey.setText(getConsumerKey());\n" " \n" " var consumerSecretLabel = app.createLabel(\"Fitbit OAuth Consumer Secret:*\");\n" " var consumerSecret = app.createTextBox();\n" " consumerSecret.setName(\"consumerSecret\");\n" " consumerSecret.setWidth(\"100%\");\n" " consumerSecret.setText(getConsumerSecret());\n" " \n" " var projectKeyTitleLabel = app.createLabel(\"Project key: \");\n" " var projectKeyLabel = app.createLabel(ScriptApp.getProjectKey());\n" " \n" " var firstDate = app.createTextBox().setId(\"firstDate\").setName(\"firstDate\");\n" " firstDate.setName(\"firstDate\");\n" " firstDate.setWidth(\"100%\");\n" " firstDate.setText(getFirstDate());\n\n" " var lastDate = app.createTextBox().setId(\"lastDate\").setName(\"lastDate\");\n" " lastDate.setName(\"lastDate\");\n" " lastDate.setWidth(\"100%\");\n" " lastDate.setText(getLastDate());\n" " // create the save handler and button\n" " var saveHandler = app.createServerClickHandler(\"saveSetup\");\n" " var saveButton = app.createButton(\"Save Setup\", saveHandler);\n\n" " // put the controls in a grid\n" " var listPanel = app.createGrid(8, 3);\n" " listPanel.setWidget(1, 0, consumerKeyLabel);\n" " listPanel.setWidget(1, 1, consumerKey);\n" " listPanel.setWidget(2, 0, consumerSecretLabel);\n" " listPanel.setWidget(2, 1, consumerSecret);\n" " listPanel.setWidget(3, 0, app.createLabel(\" * (obtain these at dev.fitbit.com, use OAuth2.0)\"));\n" " listPanel.setWidget(4, 0, projectKeyTitleLabel);\n" " listPanel.setWidget(4, 1, projectKeyLabel);\n" " listPanel.setWidget(5, 0, app.createLabel(\"Start Date for download (yyyy-mm-dd)\"));\n" " listPanel.setWidget(5, 1, firstDate);\n" " listPanel.setWidget(6, 0, app.createLabel(\"End date for download (yyyy-mm-dd)\"));\n" " listPanel.setWidget(6, 1, lastDate);\n" " listPanel.setWidget(7, 0, app.createLabel(\"Very long intervals will not work; exceed Fitbit rate limit and/or function will timeout\"));\n" " \n" " // Ensure that all controls in the grid are handled\n" " saveHandler.addCallbackElement(listPanel);\n" " // Build a FlowPanel, adding the grid and the save button\n" " var dialogPanel = app.createFlowPanel();\n" " dialogPanel.add(listPanel);\n" " dialogPanel.add(saveButton);\n" " app.add(dialogPanel);\n" " doc.show(app);\n" "}\n\n" "function getFitbitService() {\n" " // Create a new service with the given name. The name will be used when\n" " // persisting the authorized token, so ensure it is unique within the\n" " // scope of the property store\n" " Logger.log(PropertiesService.getUserProperties());\n" " return OAuth2.createService(SERVICE_IDENTIFIER)\n\n" " // Set the endpoint URLs, which are the same for all Google services.\n" " .setAuthorizationBaseUrl('https://www.fitbit.com/oauth2/authorize')\n" " .setTokenUrl('https://api.fitbit.com/oauth2/token')\n\n" " // Set the client ID and secret, from the Google Developers Console.\n" " .setClientId(getConsumerKey())\n" " .setClientSecret(getConsumerSecret())\n\n" " // Set the name of the callback function in the script referenced\n" " // above that should be invoked to complete the OAuth flow.\n" " .setCallbackFunction('authCallback')\n\n" " // Set the property store where authorized tokens should be persisted.\n" " .setPropertyStore(PropertiesService.getUserProperties())\n\n" " .setScope('activity profile')\n" " \n" " .setTokenHeaders({\n" " 'Authorization': 'Basic ' + Utilities.base64Encode(getConsumerKey() + ':' + getConsumerSecret())\n" " });\n\n" "}\n\n" "function clearService(){\n" " OAuth2.createService(SERVICE_IDENTIFIER)\n" " .setPropertyStore(PropertiesService.getUserProperties())\n" " .reset();\n" "}\n\n" "function showSidebar() {\n" " var service = getFitbitService();\n" " if (!service.hasAccess()) {\n" " var authorizationUrl = service.getAuthorizationUrl();\n" " var template = HtmlService.createTemplate(\n" " '<a href=\"<?= authorizationUrl ?>\" target=\"_blank\">Authorize</a>. ' +\n" " 'Reopen the sidebar when the authorization is complete.');\n" " template.authorizationUrl = authorizationUrl;\n" " var page = template.evaluate();\n" " SpreadsheetApp.getUi().showSidebar(page);\n" " } else {\n" " Logger.log(\"Has access!!!!\");\n" " }\n" "}\n\n" "function authCallback(request) {\n" " Logger.log(\"authcallback\");\n" " var service = getFitbitService();\n" " var isAuthorized = service.handleCallback(request);\n" " if (isAuthorized) {\n" " Logger.log(\"success\");\n" " return HtmlService.createHtmlOutput('Success! You can close this tab.');\n" " } else {\n" " Logger.log(\"denied\");\n" " return HtmlService.createHtmlOutput('Denied. You can close this tab');\n" " }\n" "}\n\n" "function getUser() {\n" " var service = getFitbitService();\n\n" " var options = {\n" " headers: {\n" " \"Authorization\": \"Bearer \" + service.getAccessToken(),\n" " \"method\": \"GET\"\n" " }};\n" " var response = UrlFetchApp.fetch(\"https://api.fitbit.com/1/user/-/profile.json\",options);\n" " var o = JSON.parse(response.getContentText());\n" " return o.user;\n" "}\n\n" "function refreshTimeSeries() {\n" " if (!isConfigured()) {\n" " setup();\n" " return;\n" " }\n" " var user = getUser();\n" " var doc = SpreadsheetApp.getActiveSpreadsheet();\n" " doc.setFrozenRows(2);\n" " // two header rows\n" " doc.getRange(\"a1\").setValue(user.fullName);\n" " doc.getRange(\"a1\").setComment(\"DOB:\" + user.dateOfBirth)\n" " doc.getRange(\"b1\").setValue(user.country + \"/\" + user.state + \"/\" + user.city);\n\n" " var options =\n" " {headers:{\n" " \"Authorization\": 'Bearer ' + getFitbitService().getAccessToken(),\n" " \"method\": \"GET\"\n" " }};\n" " var activities = [\"activities/log/steps\"];\n" " var intradays = [\"activities-log-steps-intraday\"];\n\n" " var lastIndex = 0;\n" " for (var activity in activities) {\n" " var index = 0;\n" " var dateString = getFirstDate();\n" " date = parseDate(dateString);\n" " var table = new Array();\n" " while (1) {\n" " var currentActivity = activities[activity];\n" " try {\n" " var result = UrlFetchApp.fetch(\"https://api.fitbit.com/1/user/-/\" + currentActivity + \"/date/\" + dateString+ \"/\" + dateString + \".json\", options);\n" " } catch(exception) {\n" " Logger.log(exception);\n" " }\n" " var o = JSON.parse(result.getContentText());\n\n" " var cell = doc.getRange('a3');\n" " var titleCell = doc.getRange(\"a2\");\n" " titleCell.setValue(\"Date\");\n" " var title = currentActivity.split(\"/\");\n" " title = title[title.length - 1];\n" " titleCell.offset(0, 1 + activity * 1.0).setValue(title);\n" " var row = o[intradays[activity]][\"dataset\"];\n" " for (var j in row) {\n" " var val = row[j];\n" " var arr = new Array(2);\n" " arr[0] = dateString + ' ' + val[\"time\"];\n" " arr[1] = val[\"value\"];\n" " table.push(arr);\n" " // set the value index index\n" " index++;\n" " }\n" " date.setDate(date.getDate()+1);\n" " dateString = Utilities.formatDate(date, \"GMT\", \"yyyy-MM-dd\");\n" " if (dateString > getLastDate()) {\n" " break;\n" " }\n\n" " }\n" " \n" " // Batch set values of table, much faster than doing each time per loop run, this wouldn't work as is if there were multiple activities being listed\n" " doc.getRange(\"A3:B\"+(table.length+2)).setValues(table);\n" " }\n" "}\n" "// parse a date in yyyy-mm-dd format\n" "function parseDate(input) {\n" " var parts = input.match(/(\\d+)/g);\n" " // new Date(year, month [, date [, hours[, minutes[, seconds[, ms]]]]])\n" " return new Date(parts[0], parts[1]-1, parts[2]); // months are 0-based\n" "}\n\n" "// parse a date in 2011-10-25T23:57:00.000 format\n" "function parseDate2(input) {\n" " var parts = input.match(/(\\d+)/g);\n" " return new Date(parts[0], parts[1]-1, parts[2], parts[3], parts[4]);\n" "}") subst = "\\2'\\4\\5\\8" # You can manually specify the number of replacements by changing the 4th argument result = re.sub(regex, subst, test_str, 0, re.MULTILINE) if result: print (result) # Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

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 Python, please visit: https://docs.python.org/3/library/re.html