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

/
/
gm

Test String

Substitution

Processing...

Code Generator

Generated Code

#include <MsgBoxConstants.au3> ; to declare the Constants of MsgBox Local $sRegex = "(?m)\/\*\*?\s*([\W\w]*?)\s*\*\/|\/\/\s*(.*)$" Local $sString = "/**" & @CRLF & _ " * The Crypto Info Bot" & @CRLF & _ " *" & @CRLF & _ " * @author Denis Efremov <efremov.a.denis@gmail.com>" & @CRLF & _ " */" & @CRLF & _ "require('dotenv').load()" & @CRLF & _ "" & @CRLF & _ "const axios = require('axios')" & @CRLF & _ "const winston = require('winston')" & @CRLF & _ "const { inspect } = require('util')" & @CRLF & _ "const Telegraf = require('telegraf')" & @CRLF & _ "" & @CRLF & _ "const { session } = Telegraf" & @CRLF & _ "const {" & @CRLF & _ " API_URL," & @CRLF & _ " BOT_TOKEN," & @CRLF & _ " BOT_USERNAME," & @CRLF & _ " PAGE_SIZE," & @CRLF & _ " FIXED_LENGTH," & @CRLF & _ "} = process.env" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Debug helper" & @CRLF & _ " *" & @CRLF & _ " * @param {Mixed} data The data" & @CRLF & _ " * @return {Mixed}" & @CRLF & _ " */" & @CRLF & _ "const debug = (data) => console.log(inspect(data, {" & @CRLF & _ " showHidden: true," & @CRLF & _ " colors: true," & @CRLF & _ " depth: 10," & @CRLF & _ "}))" & @CRLF & _ "" & @CRLF & _ "const logger = winston.createLogger({" & @CRLF & _ " level: 'info'," & @CRLF & _ " format: winston.format.json()," & @CRLF & _ " transports: [" & @CRLF & _ " new winston.transports.File({ filename: 'log/error.log', level: 'error' })," & @CRLF & _ " new winston.transports.File({ filename: 'log/combined.log' })," & @CRLF & _ " ]," & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "const formattedTime = (date) => date.toTimeString()" & @CRLF & _ "const formattedDate = (date) => date.toDateString()" & @CRLF & _ "const formattedDateTime = (date) => \`${formattedDate(date)} ${formattedTime(date)}\`" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Create a new bot instance" & @CRLF & _ " *" & @CRLF & _ " * @type {Telegraf}" & @CRLF & _ " */" & @CRLF & _ "const bot = new Telegraf(BOT_TOKEN, { username: BOT_USERNAME })" & @CRLF & _ "" & @CRLF & _ "bot.use(session())" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Render pagination buttons" & @CRLF & _ " *" & @CRLF & _ " * @param {String} ns The namespace" & @CRLF & _ " * @param {Number} page The page" & @CRLF & _ " * @param {Number} total The total" & @CRLF & _ " * @return {Object} Message parameters" & @CRLF & _ " */" & @CRLF & _ "const pagination = (namespace, page, total) => ({" & @CRLF & _ " reply_markup: {" & @CRLF & _ " inline_keyboard: [[" & @CRLF & _ " page !== 0" & @CRLF & _ " ? { text: `< Prev ${PAGE_SIZE}`, callback_data: `/${namespace}/prev` }" & @CRLF & _ " : { text: '----------', callback_data: '/noop' }," & @CRLF & _ " {" & @CRLF & _ " text: `${page * PAGE_SIZE} - ${(page + 1) * PAGE_SIZE} (${total})`," & @CRLF & _ " callback_data: '/noop'," & @CRLF & _ " }," & @CRLF & _ " page !== (total / PAGE_SIZE) - 1" & @CRLF & _ " ? { text: `Next ${PAGE_SIZE} >`, callback_data: `/${namespace}/next` }" & @CRLF & _ " : { text: '----------', callback_data: '/noop' }," & @CRLF & _ " ]]," & @CRLF & _ " }," & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Gets the rates." & @CRLF & _ " *" & @CRLF & _ " * @param {Number} start The start" & @CRLF & _ " * @param {Number} limit The limit" & @CRLF & _ " * @return {Promise} The rates" & @CRLF & _ " */" & @CRLF & _ "const getRates = (start, limit) => {" & @CRLF & _ " let url = `${API_URL}?convert=RUB`" & @CRLF & _ "" & @CRLF & _ " if (limit) {" & @CRLF & _ " url += `&limit=${limit}`" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if (start) {" & @CRLF & _ " url += `&start=${start}`" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " return axios.get(url)" & @CRLF & _ "}" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Gets the rate." & @CRLF & _ " *" & @CRLF & _ " * @param {String} asset The asset" & @CRLF & _ " * @return {Promise} The rate" & @CRLF & _ " */" & @CRLF & _ "const getRate = (asset) => axios.get(`${API_URL}${asset}/?convert=RUB`)" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * A currency message template" & @CRLF & _ " *" & @CRLF & _ " * @param {Object} rate The rate object" & @CRLF & _ " * @param {String} rate.name The name" & @CRLF & _ " * @param {String} rate.symbol The symbol" & @CRLF & _ " * @param {Number} rate.price_usd The price usd" & @CRLF & _ " * @param {Number} rate.price_rub The price rub" & @CRLF & _ " * @param {Number} rate.percent_change_1h:hour The percent change 1 h hour" & @CRLF & _ " * @param {Number} rate.percent_change_24h:day The percent change 24 h day" & @CRLF & _ " * @param {Number} rate.percent_change_7d:week The percent change 7 d week" & @CRLF & _ " * @return {String}" & @CRLF & _ " */" & @CRLF & _ "const templateMd = ({" & @CRLF & _ " name, symbol, price_usd, price_rub," & @CRLF & _ " percent_change_1h: hour," & @CRLF & _ " percent_change_24h: day," & @CRLF & _ " percent_change_7d: week," & @CRLF & _ "}) => `${name} *(${symbol})* \`!${symbol.toLowerCase()}\`" & @CRLF & _ "\`\`\`" & @CRLF & _ "==================" & @CRLF & _ "$ ${price_usd}" & @CRLF & _ "₽ ${price_rub}" & @CRLF & _ "==================" & @CRLF & _ "${hour > 0 ? '+' : ''}${parseFloat(hour).toFixed(FIXED_LENGTH)}% / 1h" & @CRLF & _ "${day > 0 ? '+' : ''}${parseFloat(day).toFixed(FIXED_LENGTH)}% / 24h" & @CRLF & _ "${week > 0 ? '+' : ''}${parseFloat(week).toFixed(FIXED_LENGTH)}% / 7d" & @CRLF & _ "\`\`\``" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * A currency message small template" & @CRLF & _ " *" & @CRLF & _ " * @param {Object} rate The rate object" & @CRLF & _ " * @param {String} rate.name The name" & @CRLF & _ " * @param {String} rate.symbol The symbol" & @CRLF & _ " * @param {Number} rate.price_usd The price usd" & @CRLF & _ " * @param {Number} rate.price_rub The price rub" & @CRLF & _ " * @return {String}" & @CRLF & _ " */" & @CRLF & _ "const smallTemplateMd = ({ name, symbol, price_usd, price_rub }) => `" & @CRLF & _ "${name} *(${symbol})* \`!${symbol.toLowerCase()}\`" & @CRLF & _ "\`\`\`" & @CRLF & _ "$ ${price_usd} | ₽ ${price_rub}" & @CRLF & _ "\`\`\``" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Map command listaners" & @CRLF & _ " *" & @CRLF & _ " * @param {Object[]} rates The rates" & @CRLF & _ " * @return {Promise}" & @CRLF & _ " */" & @CRLF & _ "const mapCommands = async (/*rates*/) => rates.reduce((acc, rate) => {" & @CRLF & _ " const command = rate.symbol.toLowerCase()" & @CRLF & _ "" & @CRLF & _ " bot.hears(`!${command}`, async (ctx) => {" & @CRLF & _ " let intervalId" & @CRLF & _ " let response = await getRate(ctx.index[command]).catch((error) => {" & @CRLF & _ " debug(error)" & @CRLF & _ " clearInterval(intervalId)" & @CRLF & _ " })" & @CRLF & _ " let text = templateMd(response.data[0])" & @CRLF & _ " let message = await ctx.replyWithMarkdown(" & @CRLF & _ " `${text}" & @CRLF & _ "Updated: ${formattedTime(new Date()).slice(0, 8)}`" & @CRLF & _ " ).catch((error) => {" & @CRLF & _ " debug(error)" & @CRLF & _ " clearInterval(intervalId)" & @CRLF & _ " })" & @CRLF & _ "" & @CRLF & _ " message.text = text" & @CRLF & _ "" & @CRLF & _ " intervalId = setInterval(async () => {" & @CRLF & _ " response = await getRate(ctx.index[command]).catch((error) => {" & @CRLF & _ " debug(error)" & @CRLF & _ " clearInterval(intervalId)" & @CRLF & _ " })" & @CRLF & _ "" & @CRLF & _ " text = templateMd(response.data[0])" & @CRLF & _ "" & @CRLF & _ " if (text === message.text) {" & @CRLF & _ " return" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " message = await ctx.tg.editMessageText(" & @CRLF & _ " ctx.chat.id," & @CRLF & _ " message.message_id," & @CRLF & _ " undefined," & @CRLF & _ " `${text}" & @CRLF & _ "Updated: ${formattedTime(new Date()).slice(0, 8)}`," & @CRLF & _ " { parse_mode: 'Markdown' }" & @CRLF & _ " ).catch((error) => {" & @CRLF & _ " debug(error)" & @CRLF & _ " clearInterval(intervalId)" & @CRLF & _ " })" & @CRLF & _ " message.text = text" & @CRLF & _ " }, 5000)" & @CRLF & _ " })" & @CRLF & _ "" & @CRLF & _ " acc[command] = rate.id" & @CRLF & _ "" & @CRLF & _ " return acc" & @CRLF & _ "}, {})" & @CRLF & _ "" & @CRLF & _ "bot.use((ctx, next) => {" & @CRLF & _ " logger.log({ level: 'info', message: ctx.message })" & @CRLF & _ " debug(ctx.message)" & @CRLF & _ " next()" & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * The rates command" & @CRLF & _ " *" & @CRLF & _ " * @param {TelegrafContext} ctx The bot's context" & @CRLF & _ " */" & @CRLF & _ "bot.hears('!rates', async (ctx) => {" & @CRLF & _ " ctx.session.ratesPage = ctx.session.ratesPage || 0" & @CRLF & _ "" & @CRLF & _ " const { data } = await getRates(" & @CRLF & _ " ctx.session.ratesPage * PAGE_SIZE," & @CRLF & _ " (ctx.session.ratesPage * PAGE_SIZE) + PAGE_SIZE" & @CRLF & _ " )" & @CRLF & _ "" & @CRLF & _ " await ctx.replyWithMarkdown(" & @CRLF & _ " data.map(smallTemplateMd).join('')," & @CRLF & _ " pagination('rates', ctx.session.ratesPage, Object.keys(ctx.index).length)," & @CRLF & _ " ).catch(debug)" & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * The time command" & @CRLF & _ " *" & @CRLF & _ " * @param {TelegrafContext} ctx The bot's context" & @CRLF & _ " */" & @CRLF & _ "bot.hears('!time', async (ctx) => {" & @CRLF & _ " const message = await ctx.replyWithMarkdown(formattedDateTime(new Date()))" & @CRLF & _ " .catch(debug)" & @CRLF & _ "" & @CRLF & _ " const intervalId = setInterval(async () => {" & @CRLF & _ " await ctx.tg.editMessageText(" & @CRLF & _ " ctx.chat.id," & @CRLF & _ " message.message_id," & @CRLF & _ " undefined," & @CRLF & _ " formattedDateTime(new Date())" & @CRLF & _ " ).catch((error) => {" & @CRLF & _ " debug(error)" & @CRLF & _ " clearInterval(intervalId)" & @CRLF & _ " })" & @CRLF & _ " }, 3000)" & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * The currencies list command" & @CRLF & _ " *" & @CRLF & _ " * @param {TelegrafContext} ctx The bot's context" & @CRLF & _ " */" & @CRLF & _ "bot.hears('!list', async (ctx) => {" & @CRLF & _ " const text = Object.keys(ctx.index)" & @CRLF & _ " .map((key) => `" & @CRLF & _ "${ctx.index[key]} \`!${key}\``)" & @CRLF & _ " .join('')" & @CRLF & _ "" & @CRLF & _ " await ctx.replyWithMarkdown(text).catch(debug)" & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Change page action" & @CRLF & _ " *" & @CRLF & _ " * @param {TelegrafContext} ctx The bot's context" & @CRLF & _ " */" & @CRLF & _ "bot.action(/^/rates/(w+)$/, async (ctx) => {" & @CRLF & _ " const current = ctx.session.ratesPage || 0" & @CRLF & _ " const allKeys = Object.keys(ctx.index)" & @CRLF & _ " // klskdlskakdsl" & @CRLF & _ " switch (ctx.match[1]) {" & @CRLF & _ " case 'prev':" & @CRLF & _ " ctx.session.ratesPage = current > 0" & @CRLF & _ " ? current - 1 // slklklkl" & @CRLF & _ " : 0" & @CRLF & _ " break" & @CRLF & _ " case 'next':" & @CRLF & _ " ctx.session.ratesPage = current < (allKeys.length / PAGE_SIZE) - 1" & @CRLF & _ " ? current + 1" & @CRLF & _ " : (allKeys.length / PAGE_SIZE) - 1" & @CRLF & _ " break" & @CRLF & _ " default:" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " const { data } = await getRates(ctx.session.ratesPage * PAGE_SIZE, PAGE_SIZE)" & @CRLF & _ " .catch(debug)" & @CRLF & _ "" & @CRLF & _ " await ctx.editMessageText(" & @CRLF & _ " data.map(smallTemplateMd).join('')," & @CRLF & _ " {" & @CRLF & _ " disable_web_page_preview: true," & @CRLF & _ " parse_mode: 'Markdown'," & @CRLF & _ " ...pagination('rates', ctx.session.ratesPage, allKeys.length)," & @CRLF & _ " }" & @CRLF & _ " ).catch(debug)" & @CRLF & _ "" & @CRLF & _ " return ctx.answerCbQuery()" & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Handles noop actions" & @CRLF & _ " *" & @CRLF & _ " * @param {TelegrafContext} ctx The bot's context" & @CRLF & _ " */" & @CRLF & _ "bot.action(/^/noop$/, async (ctx) => ctx.answerCbQuery())" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Handles the help command" & @CRLF & _ " */" & @CRLF & _ "bot.command('help', async (ctx) => {" & @CRLF & _ " const message = await ctx.replyWithMarkdown(`" & @CRLF & _ "*Usage:*" & @CRLF & _ "" & @CRLF & _ "\`!list\` - List of all supported currencies without rates" & @CRLF & _ "\`!rates\` - Paginated list of all supported currencies with rates" & @CRLF & _ "\`!{TICKER}\` - Show rate of exact currency by its ticker" & @CRLF & _ "`)" & @CRLF & _ "" & @CRLF & _ " if (message) {" & @CRLF & _ " setTimeout(() => {" & @CRLF & _ " ctx.deleteMessage(message.message_id)" & @CRLF & _ " }, 7000)" & @CRLF & _ " }" & @CRLF & _ "})" & @CRLF & _ "" & @CRLF & _ "// bot.command('leave', async (ctx) => {" & @CRLF & _ "// ctx.tg.leaveChat(ctx.chat.id)" & @CRLF & _ "// })" & @CRLF & _ "" & @CRLF & _ "// bot.on('inline_query', async (ctx) => {" & @CRLF & _ "" & @CRLF & _ "// })" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Init the bot" & @CRLF & _ " *" & @CRLF & _ " * @param {TelegrafContext} ctx The bot's context" & @CRLF & _ " */" & @CRLF & _ "const run = async (instance) => {" & @CRLF & _ " const { data } = await getRates().catch(console.log)" & @CRLF & _ "" & @CRLF & _ " instance.context.index = await mapCommands(data)" & @CRLF & _ " return instance" & @CRLF & _ "}" & @CRLF & _ "" & @CRLF & _ "/**" & @CRLF & _ " * Start the bot" & @CRLF & _ " *" & @CRLF & _ " * @param {Telegraf} instance The bot instance" & @CRLF & _ " */" & @CRLF & _ "run(bot).then((instance) => {" & @CRLF & _ " instance.startPolling()" & @CRLF & _ "})" Local $sSubst = "" 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