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

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

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 AutoIt, please visit: https://www.autoitscript.com/autoit3/docs/functions/StringRegExp.htm