Regular Expressions 101

Save & Manage Regex

  • Current Version: 1
  • Save & Share
  • Community Library

Flavor

  • PCRE2 (PHP)
  • ECMAScript (JavaScript)
  • Python
  • Golang
  • Java
  • .NET 7.0 (C#)
  • Rust
  • PCRE (Legacy)
  • Regex Flavor Guide

Function

  • Match
  • Substitution
  • List
  • Unit Tests
Sponsors
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
Processing...

Test String

Substitution
Processing...

Code Generator

Generated Code

import re regex = re.compile(r"^(/\*)(\n)(\*)(.*?)(\n)(\*/$)|(?<!:)(//)(.*?)$", flags=re.MULTILINE) 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" result = regex.sub(subst, test_str) if result: print(result)

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