Quick answer
To trim whitespace with a regex, replace ^\s+|\s+$ with an empty string using the g flag: the first alternative removes spaces, tabs and line breaks at the start, the second removes them at the end, and inner spaces are left alone. In JavaScript, String.prototype.trim() does the same job faster, so use the regex when you need a variant such as trimming every line with the m flag.
- Tested examples
- Token-by-token breakdown
- Code in 5 languages
- Live tester
How to use the leading and trailing whitespace regex
- 1Copy the pattern with Copy pattern in the tester, or take a snippet for your language from the code section below.
- 2Look at the sample in Test string: every leading and trailing whitespace the regex finds is highlighted.
- 3Paste your own text to see the matches, then switch to Replace to preview a replacement.
- 4Open the Code tab for JavaScript, Python, Go, C#, PHP or Dart with the pattern translated and escaped.
How does the leading and trailing whitespace regex work?
Read it left to right. Each piece below matches one part of the input:
^\s+One or more whitespace characters at the start of the string.|Or.\s+$One or more whitespace characters at the end of the string.g flagGlobal, so both the leading and the trailing run are replaced, not just the first.
Flags: g (global).
Which strings does the leading and trailing whitespace regex match?
The pattern searches inside the text, so a match can be part of a longer string. Every row below is checked against the pattern by our automated test suite before each release.
| Input | Finds a match? | Why |
|---|---|---|
··hello·world·· | Yes | Spaces at both ends are matched; the inner space is not. |
→hello | Yes | A leading tab. |
hello↵ | Yes | A trailing newline, typical of file contents. |
hello·world | No | Nothing to trim: the inner space is untouched. |
hello | No | No whitespace at all. |
a·b→c | No | Whitespace between words only: nothing at either end. |
Replacing every match with an empty string (text.replace(regex, "")):
| Before | After |
|---|---|
··hello·world·· | hello·world |
→hello | hello |
hello↵ | hello |
·↵→·padded·→↵· | padded |
Why can this regex be slow on long strings?
The second alternative, \s+$, is the classic trap. Given a long run of spaces that is not at the end (say 20,000 spaces followed by a letter), the engine starts at every space, consumes the rest of the run, fails to find the end, and backs off one character at a time. That is quadratic work: the run of spaces is scanned again from every starting position.
A pattern of this shape (^[\s\u200c]+|[\s\u200c]+$) took Stack Overflow offline for 34 minutes on July 20, 2016, when a post with about 20,000 consecutive whitespace characters reached the home page. Two fixes:
- Use the built-in:
str.trim()in JavaScript,str.strip()in Python,strings.TrimSpacein Go,String.Trim()in C#,trim()in PHP. They scan from each end and never backtrack. - If you need a regex, trim the end with a non-backtracking approach, or cap the input length first.
How do I trim every line, or collapse inner spaces?
Common variations, all used with replace:
- Trim every line:
^[ \t]+|[ \t]+$with flagsgm, replaced with an empty string. - Collapse runs of spaces:
[ \t]{2,}withg, replaced with a single space. - Remove blank lines:
^\s*\nwithgm, replaced with an empty string. - Normalize all whitespace:
\s+withg, replaced with a single space, then trimmed.
Use [ \t] rather than \s in multiline mode, because \s also matches the line breaks and would join lines together. In JavaScript, \s covers Unicode spaces such as the non-breaking space (U+00A0) as well, which is usually what you want when cleaning pasted text.
How do I use the leading and trailing whitespace regex in JavaScript, Python, Go, C# and PHP?
The pattern is translated for each engine rather than pasted as is: named groups, anchors, escapes, shorthand classes and flags are adjusted so each snippet behaves as closely to the JavaScript version as its engine allows. Differences that remain (Go's RE2 has no lookarounds or backreferences, for example) are called out under each one. The Code tab in the tester above also exports Dart, and updates as you edit the pattern.
JavaScript and TypeScript
const regex = /^\s+|\s+$/g;
const text = " hello world ";
for (const match of text.matchAll(regex)) {
console.log(match[0], "at index", match.index);
}
const result = text.replace(regex, "");
console.log(result);Python
import re
pattern = re.compile(r"^\s+|\s+\Z")
text = " hello world "
for match in pattern.finditer(text):
print(match.group(0), "at index", match.start())
result = pattern.sub(r"", text)
print(result)- JavaScript's $ only matches at the very end of the string. Python's $ also matches before a trailing newline, so the pattern uses \Z instead.
Go
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`^\s+|\s+$`)
text := " hello world "
for _, m := range re.FindAllStringSubmatch(text, -1) {
fmt.Println(m[0])
}
result := re.ReplaceAllString(text, "")
fmt.Println(result)
}- Go's \s only matches space, \t, \n, \f and \r; JavaScript's also matches the non-breaking space and other Unicode spaces.
C#
using System;
using System.Text.RegularExpressions;
// The timeout stops a pathological input from hanging the thread (ReDoS).
var regex = new Regex(@"^\s+|\s+\z", RegexOptions.None, TimeSpan.FromSeconds(1));
var text = " hello world ";
foreach (Match match in regex.Matches(text))
{
Console.WriteLine($"{match.Value} at index {match.Index}");
}
var result = regex.Replace(text, @"");
Console.WriteLine(result);- JavaScript's $ only matches at the very end of the string. .NET's $ also matches before a trailing newline, so the pattern uses \z instead.
PHP
<?php
$pattern = '/^\s+|\s+$/D';
$text = ' hello world ';
preg_match_all($pattern, $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
foreach ($matches as $match) {
echo $match[0][0], " at index ", $match[0][1], PHP_EOL;
}
$result = preg_replace($pattern, '', $text);
echo $result, PHP_EOL;- PCRE's \s matches ASCII whitespace unless Unicode properties (UCP) are on; JavaScript's also matches the non-breaking space and other Unicode spaces.
- The D modifier makes $ match only at the very end, like JavaScript (PCRE's $ also matches before a trailing newline).
Which related regex patterns are useful?
- Regex for Alphanumeric Characters: Letters A–Z and digits only, with a Unicode variant for every script.
- Regex for Numbers Only: Digits only, plus variants for signs, decimals and thousands separators.
- Regex for HTML Tags: Opening, closing and self-closing tags, capturing the tag name.
- Regex for URL Slugs: Lowercase letters and digits separated by single hyphens, like regex-tester.
Browse all 25 patterns in the regex pattern library, or build your own in the regex tester.
Frequently asked questions
Last updated by the Playxoft engineering team.