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

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