31

I am using the following Regular Expresion to remove html tags from a string. It works except I leave the closing tag. If I attempt to remove: <a href="blah">blah</a> it leaves the <a/>.

I do not know Regular Expression syntax at all and fumbled through this. Can someone with RegEx knowledge please provide me with a pattern that will work.

Here is my code:

  string sPattern = @"<\/?!?(img|a)[^>]*>";
  Regex rgx = new Regex(sPattern);
  Match m = rgx.Match(sSummary);
  string sResult = "";
  if (m.Success)
   sResult = rgx.Replace(sSummary, "", 1);

I am looking to remove the first occurence of the <a> and <img> tags.

6
  • A sample before and after string would help Commented Sep 24, 2010 at 20:23
  • 16
    "I am using ... Regular Expresion to remove html tags" there's your problem. Use an HTML parser instead. Commented Sep 24, 2010 at 20:24
  • 1
    possible duplicate of RegEx match open tags except XHTML self-contained tags -- in spite of the title, this is an exact dupe. Promise. Commented Sep 24, 2010 at 20:25
  • 5
    necessary link is necessary Commented Sep 24, 2010 at 20:26
  • Since other people can't see the possible use-case for this, here's mine... a) working within a code sandbox (Salesforce) where it is difficult, if not impossible, to include and maintain a 3rd-party library b) only trying to strip tags out of an email body for a cleaner email-to-case description (i.e. - no security issues involved) c) the stripHtmlTags() method did not do a sufficient job of removing the extra tags Commented Aug 2, 2018 at 16:02

18 Answers 18

29

To turn this:

'<td>mamma</td><td><strong>papa</strong></td>'

into this:

'mamma papa'

You need to replace the tags with spaces:

.replace(/<[^>]*>/g, ' ')

and reduce any duplicate spaces into single spaces:

.replace(/\s{2,}/g, ' ')

then trim away leading and trailing spaces with:

.trim();

Meaning that your remove tag function look like this:

function removeTags(string){
  return string.replace(/<[^>]*>/g, ' ')
               .replace(/\s{2,}/g, ' ')
               .trim();
}
Sign up to request clarification or add additional context in comments.

4 Comments

this is a great answer, how would you change it, if you wanted to strip out all tags including the text content of the tags? just leaving behind text that was not inside tags?
ahhh i figured it out, i came up with: function removeTags(string){ return string.replace(/<[^>]*>.*?(<[^>]*>)?/g, ' ') .replace(/\s{2,}/g, ' ') .trim(); }
This is trivially broken, and should never be used for any reason. If you really want to sanitize HTML, use something that's actually aware of the HTML grammar. Try it against this input, which loads a 1px GIF, then assuming jQuery is present, loads a script: <img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAA‌​QABAAACAkQBADs=" onload="$.getScript('evil.js');1<2>3">. It won't correctly remove that element, even though it is supposed to.
Isiah, the "any reason" part of your warning does not quite fit this question. To use regexp to remove somthing from a string sounded to me like a very controlled environment. If the task was to do content scraping or somthing more dynamic like your example suggests, I agree that the solution is not some impro regexp. Here's an article about a "bazillion different packages" for a start.
28

Using a regular expression to parse HTML is fraught with pitfalls. HTML is not a regular language and hence can't be 100% correctly parsed with a regex. This is just one of many problems you will run into. The best approach is to use an HTML / XML parser to do this for you.

Here is a link to a blog post I wrote awhile back which goes into more details about this problem.

That being said, here's a solution that should fix this particular problem. It in no way is a perfect solution though.

var pattern = @"<(img|a)[^>]*>(?<content>[^<]*)<";
var regex = new Regex(pattern);
var m = regex.Match(sSummary);
if ( m.Success ) { 
  sResult = m.Groups["content"].Value;

2 Comments

Jared, this seems to throw an exception when I try it. Also, will this remove the text between the tags? I essentially want to remove the first occurence of the a, p and img tags from the string.
@Tony, fixed a bug in the regex. Should compile now
9

In order to remove also spaces between tags, you can use the following method a combination between regex and a trim for spaces at start and end of the input html:

    public static string StripHtml(string inputHTML)
    {
        const string HTML_MARKUP_REGEX_PATTERN = @"<[^>]+>\s+(?=<)|<[^>]+>";
        inputHTML = WebUtility.HtmlDecode(inputHTML).Trim();

        string noHTML = Regex.Replace(inputHTML, HTML_MARKUP_REGEX_PATTERN, string.Empty);

        return noHTML;
    }

So for the following input:

      <p>     <strong>  <em><span style="text-decoration:underline;background-color:#cc6600;"></span><span style="text-decoration:underline;background-color:#cc6600;color:#663333;"><del>   test text  </del></span></em></strong></p><p><strong><span style="background-color:#999900;"> test 1 </span></strong></p><p><strong><em><span style="background-color:#333366;"> test 2 </span></em></strong></p><p><strong><em><span style="text-decoration:underline;background-color:#006600;"> test 3 </span></em></strong></p>      

The output will be only the text without spaces between html tags or space before or after html: "   test text   test 1  test 2  test 3 ".

Please notice that the spaces before test text are from the <del> test text </del> html and the space after test 3 is from the <em><span style="text-decoration:underline;background-color:#006600;"> test 3 </span></em></strong></p> html.

Comments

5

Strip off HTML Elements (with/without attributes)

/<\/?[\w\s]*>|<.+[\W]>/g

This will strip off all HTML elements and leave behind the text. This works well even for malformed HTML elements (i.e. elements that are missing closing tags)

Reference and example (Ex.10)

8 Comments

This helped me. How about if I need to search/replace specific tag? Like span?
For targeting span tags, you could either modify the accepted answer to suit your needs or use /<\/?[span]*>|<.+[\W]>/g
The regex also matches <p></p> tags.
oh yes, you are right. There is a small error in the regex given in the comments, which will also cause it to match all <a> tags. To rectify, all you need to do is, remove the square brackets around the word span. i.e. /<\/?span*>|<.+[\W]>/g
This fails on <h2 class="ofscreen">Webontwikkeling leren</h2><h1>Regular Expressions</h1><p>"Alle onderdelen van MDN (documenten en de website zelf) worden gemaakt door een open gemeenschap."</p><br/>, it selects the whole string.
|
4

can use:

Regex.Replace(source, "<[^>]*>", string.Empty);

Comments

3

So the HTML parser everyone's talking about is Html Agility Pack.

If it is clean XHTML, you can also use System.Xml.Linq.XDocument or System.Xml.XmlDocument.

Comments

3

If you need to find only the opening tags you can use the following regex, which will capture the tag type as $1 (a or img) and the content (including closing tag if there is one) as $2:

(?:<(a|img)(?:\s[^>]*)?>)((?:(?!<\1)[\s\S])*)


In case you have also closing tag you should use the following regex, which will capture the tag type as $1 (a or img) and the content as $2:

(?:<(a|img)(?:\s[^>]*)?>)\s*((?:(?!<\1)[\s\S])*)\s*(?:<\/\1>)

Basically you just need to use replace function on one of above regex, and return $2 in order to get what you wanted.

Short explanation about the query:

  • ( ) - is used for capturing whatever matches the regex inside the brackets. The order of the capturing is the order of: $1, $2 etc.
  • ?: - is used after an opening bracket "(" for not capturing the content inside the brackets.
  • \1 - is copying capture number 1, which is the tag type. I had to capture the tag type so closing tag will be consistent to the opening one and not something like: <img src=""> </a>.
  • \s - is white space, so after opening tag <img there will be at least 1 white space in case there are attributes (so it won't match <imgs> for example).
  • [^>]* - is looking for anything but the chars inside, which in this case is >, and * means for unlimited times.
  • ?! - is looking for anything but the string inside, kinda similar to [^>] just for string instead of single chars.
  • [\s\S] - is used almost like . but allow any whitespaces (which will also match in case there are new lines between the tags). If you are using regex "s" flag, then you can use . instead.

Example of using with closing tag: https://regex101.com/r/MGmzrh/1

Example of using without closing tag: https://regex101.com/r/MGmzrh/2


Regex101 also has some explanation for what i did :)

Comments

2

You can use already existing libraries to strip off the html tags. One good one being Chilkat C# Library.

1 Comment

This is all well and good, but I not onlyneed to remove the tag, I need to remove everything between the tags.
2

This piece of code could help you out easily removing any html tags:

import re
string = str(<a href="blah">blah</a>)
replaced_string = re.sub('<a.*href="blah">.*<\/a>','',string) // remember, sub takes 3 arguments.

Output is an empty string.

Comments

2

If all you're trying to do is remove the tags (and not figure out where the closing tag is), I'm really not sure why people are so fraught about it.

This Regex seems to handle anything I can throw at it:

<([\w\-/]+)( +[\w\-]+(=(('[^']*')|("[^"]*")))?)* *>

To break it down:

  • <([\w\-/]+) - match the beginning of the opening or closing tag. if you want to handle invalid stuff, you can add more here
  • ( +[\w\-]+(=(('[^']*')|("[^"]*")))?)* - this bit matches attributes [0, N] times (* at then end)
    • +[\w\-]+ - is space(s) followed by an attribute name
    • (=(('[^']*')|("[^"]*")))? - not all attributes have assignment (?)
      • ('[^']*')|("[^"]*") - of the attributes that do have assignment, the value is a string with either single or double quotes. It's not allowed to skip over a closing quote to make things work
  • *> - the whole thing ends with any number of spaces, then the closing bracket

Obviously this will mess up if someone throws super invalid html at it, but it works for anything valid I've come up with yet. Test it out here:

const regex = /<([\w\-/]+)( +[\w\-]+(=(('[^']*')|("[^"]*")))?)* *>/g;

const byId = (id) => document.getElementById(id);

function replace() {
console.log(byId("In").value)
  byId("Out").innerText = byId("In").value.replace(regex, "CUT");
}
Write your html here: <br>
<textarea id="In" rows="8" cols="50"></textarea><br>
<button onclick="replace()">Replace all tags with "CUT"</button><br>
<br>
Output:
<div id="Out"></div>

1 Comment

Doesn't work with self referencing tags
1

Remove image from the string, using a regular expression in c# (image search performed by image id)

string PRQ=<td valign=\"top\" style=\"width: 400px;\" align=\"left\"><img id=\"llgo\" src=\"http://test.Logo.png\" alt=\"logo\"></td>

var regex = new Regex("(<img(.+?)id=\"llgo\"(.+?))src=\"([^\"]+)\"");

PRQ = regex.Replace(PRQ, match => match.Groups[1].Value + "");

Comments

1

Why not trying reluctant quantifier? htmlString.replaceAll("<\\S*?>", "")

(It's Java but the main thing is to show the idea)

Comments

1

Simple way,

String html = "<a>Rakes</a> <p>paroladasdsadsa</p> My Name Rakes";

html = html.replaceAll("(<[\\w]+>)(.+?)(</[\\w]+>)", "$2");

System.out.println(html);

Comments

1

Here is the extension method I've been using for quite some time.

public static class StringExtensions
{
     public static string StripHTML(this string htmlString, string htmlPlaceHolder) {
         const string pattern = @"<.*?>";
         string sOut = Regex.Replace(htmlString, pattern, htmlPlaceHolder, RegexOptions.Singleline);
         sOut = sOut.Replace("&nbsp;", String.Empty);
         sOut = sOut.Replace("&amp;", "&");
         sOut = sOut.Replace("&gt;", ">");
         sOut = sOut.Replace("&lt;", "<");
         return sOut;
     }
}

Comments

1

My friends, I used these patterns and solved my problem with any tags.

🚩 Be cautious, it's not recommended to use with nested HTML tags:

  1. Regular way:

const str = "<h1>You are awesome!</h1>";
const nestedStr = `<p class="wrapper"><span class="you">You </span><h1 id="awesome">are awesome!</h1></p>`;

console.log("Original --> " + str);
console.log("Replaced version --> " + str.replace(/(<([^>]+)>)/gi, ""));

console.log("---------------------------------------------------");

console.log("Original Nested --> " + nestedStr);
console.log("Replaced Nested version --> " + nestedStr.replace(/(<([^>]+)>)/gi, ""));

  1. The new and safe way:

const str = "<h1>You are awesome!</h1>";
const nestedStr = `<p class="wrapper"><span class="you">You </span><h1 id="awesome">are awesome!</h1></p>`;
    
const betterClearHTMLTags = (strToSanitize) => {
   let myHTML = new DOMParser().parseFromString(strToSanitize, 'text/html');
   return myHTML.body.textContent || '';
}

console.log("Original --> " + str);
console.log("Replaced version --> " + betterClearHTMLTags(str));

console.log("---------------------------------------------------");

console.log("Original Nested --> " + nestedStr);
console.log("Replaced Nested version --> " + betterClearHTMLTags(nestedStr));

The main article: dev.to/alvisonhunter

Comments

1

Regex to remove ALL Html
No Atomic, no Assert

https://regex101.com/r/YOYd6R/1

<(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?:"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\1\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>

Comments

0

Here's an extension method I created using a simple regular expression to remove HTML tags from a string:

/// <summary>
/// Converts an Html string to plain text, and replaces all br tags with line breaks.
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
[Extension()]
public string ToPlainText(string s)
{

    s = s.Replace("<br>", Constants.vbCrLf);
    s = s.Replace("<br />", Constants.vbCrLf);
    s = s.Replace("<br/>", Constants.vbCrLf);


    s = Regex.Replace(s, "<[^>]*>", string.Empty);


    return s;
}

Hope that helps.

8 Comments

There's more than just <br> that ends with a slash; in fact, technically, any element can end with a slash -- and it might not necessarily be with one or no spaces following it or trailing it. This is also valid: <p / >
Those lines are just there to preserve line breaks, if needed. Otherwise, they may be removed.
Nice, where are you using this ? on a public web site ? entering '<script src="evil.com/evil.js" ' (notice no ">" character) is enough to exploit it :D
Rei, it will remove <p / > You haven't even tested it
VirtualBlackFox, yes I am using it on a Public web site, and quite effectively. '<script src="evil.com/evil.js" ' is malformed and will not run, so that is a moot point.
|
0

Select everything except from whats in there:

(?:<span.*?>|<\/span>|<p.*?>|<\/p>)

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.