Redundant if statement? - javascript

Is the if statement in the following example redundant?
if (str[0] === ' ') {
str = str.trimStart()
}
It seems unnecessary to me since trimStart() does not seem to have any negative effect on a string without a space at the beginning. Additionally, if the string does have a space at the beginning, you are running twice as many operations as needed.
Is the if statement ever necessary in situations like the one above?

Given the edited code, there's one situation where the if statement could be useful - if the string starts with a newline (which counts as whitespace, and would be trimmed), not a plain space. For example:
const parseStr = (str) => {
if (str[0] === ' ') {
str = str.trimStart()
}
console.log(str.length);
};
parseStr('\nfoo');
parseStr(' foo');
parseStr('foo');
If trimStart was called unconditionally, the newline would be trimmed regardless:
const parseStr = (str) => {
str = str.trimStart()
console.log(str.length);
};
parseStr('\nfoo');
parseStr(' foo');
parseStr('foo');

The if is not necessary, but you should save the trimmed value somewhere, like
str = str.trimStart();
-- Edit --
"Is the 'if' ever necessary...?"
The test that you are doing in the original is redundant. But you might want to check that str has a value and/or check that this value is a string before calling trimStart(), like
if (str && typeof str === 'string') ...

The if block isn't necessary since the trimStart function won't have any effect if there is not space in the beginning of the string. Having the if statement does not have any effect over it and wouldn't really have any real performance benefits either.

Related

How do I replace the last letter of a string element in an array with replace()

I've just started coding..I'm a super beginner and have no idea about regex yet so for now I'd rather not use it. This is an exercise I'm trying to solve. The problem is that when a word contains matching characters, the first character gets the lower case, but what I actually want is the last character of the word to become small.
I don't really require a solution for the problem. Instead I'd rather have some insight on what I'm doing wrong and maybe direct me to the right path :)
function alienLanguage(str) {
let bigWords = str.toUpperCase().split(" ");
let lastLetterSmall = [];
bigWords.forEach(words => {
lastLetterSmall
.push(words
.replace(words
.charAt(words.length -1), words.charAt(words.length -1).toLowerCase()));
});
console.log(lastLetterSmall.join(' '));
}
alienLanguage("My name is John");
alienLanguage("this is an example");
alienLanguage("Hello World");
alienLanguage("HELLO WORLD");
Since you only really want to work with indicies of the string - you don't need to replace anything dynamically other than the last index - replace won't work well, since if you pass it a string, it will only replace the first matching letter. For example:
'foo'.replace('o', 'x')
results in 'fxo', because the first o (and only the first o) gets replaced.
For your code, instead of replace, just concatenate the two parts of the string together: the part from index 0 to next-to-last index, and the character at the last index with toLowerCase() called on it:
function alienLanguage(str) {
const result = str
.toUpperCase()
.split(" ")
.map(line => line.slice(0, line.length - 1) + line[line.length - 1].toLowerCase())
.join(' ');
console.log(result);
}
alienLanguage("My name is John");
alienLanguage("this is an example");
alienLanguage("Hello World");
alienLanguage("HELLO WORLD");

javascript collapsing many spaces into one, like HTML? strange behavior

I'm encountering this weird behaviour and I don't really understand why.
I have a function to normalize strings:
function normalize_for_find(name) {
return name
.trim()
.replace(/&/g, '&')
.replace(/ /g, ' ');
}
Which if I execute in chrome console, I get " " transformed into two spaces, which is what I want:
normalize_for_find("MONKEY BISCUITS 200g")
"MONKEY BISCUITS 200g"
But then when I use it in this method, it somehow transforms " " into only one space.
function find_by_name(elems, name) {
name = normalize_for_find(name);
return _.find(elems, function(e) {
return name === normalize_for_find(e.name);
});
}
Take a look at this debugging:
name starts as "MONKEY BISCUITS 200g"
and then after the call to normalize_for_find it appears as "MONKEY BISCUITS 200g" (only one space)
I need it to be two spaces like when I execute from console.
Here is more info on watching each variable, which makes no sense to me at all!
The difference between both strings is that the original e.name contains a "non breaking space" char which is ascii code 160, while the normalize_for_find method inserts a regular space which is ascii code 32.
As suggested by another user, this can also be fixed by changing the normalize method to this:
function normalize_for_find(name) {
var parsed = jQuery.parseHTML(name);
if (!parsed || parsed.length == 0) return '';
return parsed[0].data.trim();
}
(note that jQuery.parseHTML(name) will return null for '')

How to remove spaces from an array?

I am attempting to print out several parts of an array as a string. However when I do print out the string, there are spaces before the commas which is giving me some trouble.
Here is some example code:
var Arr = [];
var foo = "Hello";
var voo = "World";
if (foo != null) {
Arr.push(foo);
}
if (voo != null) {
Arr.push(voo);
}
console.log(Arr.join(', '));
How can one print out said string without the spaces before the commas?
EDIT: I should clarify that in my actual code, I am pushing values from a tab-delimited text file into an array.
Your code should print the correct output. (Fixing the obvious typos that were in your original post). You likely have an issue with your original code (A space after what is stored in the variable foo).
var arr = [];
var foo = "Hello";
var voo = "World";
if (foo != null){
arr.push(foo);
}
if (voo != null){
arr.push(voo);
}
console.log(arr.join(', '));
Fixing all the minor errors in your code produces:
var myArray = [];
var foo = "Hello";
var voo = "World";
if (foo != null) {
myArray.push(foo);
}
if (voo != null) {
myArray.push(voo);
}
console.log(myArray.join(', '));
A brief summary:
Array is a built-in type - don’t use it as a variable name.
!- is not a valid operator, did you mean !=?
: at the end of a line is invalid syntax, did you mean ;?
console.println() doesn’t exist, did you mean console.log()?
Basically, when you joined the array, you were specifying a space after the comma, so why not remove it like below:
Arr.join(',');
So, I am assuming the spaces you mentioned are the tab spaces based on the recent question edit.
You can use regex to replace the '\t' with ' ' single space or no space as required.
foo.replace(/\t/g, "");
And if you just want to concat two strings, I wonder why you cannot just use the '+' operator with the comma rather than creating an auxiliary array to store them?
you can remove commas like this and print without space
console.log(Arr.join(''));
if you want keep space
console.log(Arr.join(' '));
3.want tab space
console.log(Arr.join('\t'));

get all single and multiline comment in javascript [duplicate]

I need to remove all JavaScript comments from a JavaScript source using the JavaScript RegExp object.
What I need is the pattern for the RegExp.
So far, I've found this:
compressed = compressed.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');
This pattern works OK for:
/* I'm a comment */
or for:
/*
* I'm a comment aswell
*/
But doesn't seem to work for the inline:
// I'm an inline comment
I'm not quite an expert for RegEx and it's patterns, so I need help.
Also, I' would like to have a RegEx pattern which would remove all those HTML-like comments.
<!-- HTML Comment //--> or <!-- HTML Comment -->
And also those conditional HTML comments, which can be found in various JavaScript sources.
Thanks.
NOTE: Regex is not a lexer or a parser. If you have some weird edge case where you need some oddly nested comments parsed out of a string, use a parser. For the other 98% of the time this regex should work.
I had pretty complex block comments going on with nested asterisks, slashes, etc. The regular expression at the following site worked like a charm:
http://upshots.org/javascript/javascript-regexp-to-remove-comments
(see below for original)
Some modifications have been made, but the integrity of the original regex has been preserved. In order to allow certain double-slash (//) sequences (such as URLs), you must use back reference $1 in your replacement value instead of an empty string. Here it is:
/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm
// JavaScript:
// source_string.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');
// PHP:
// preg_replace("/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/m", "$1", $source_string);
DEMO: https://regex101.com/r/B8WkuX/1
FAILING USE CASES: There are a few edge cases where this regex fails. An ongoing list of those cases is documented in this public gist. Please update the gist if you can find other cases.
...and if you also want to remove <!-- html comments --> use this:
/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*|<!--[\s\S]*?-->$/
(original - for historical reference only)
// DO NOT USE THIS - SEE ABOVE
/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm
try this,
(\/\*[\w\'\s\r\n\*]*\*\/)|(\/\/[\w\s\']*)|(\<![\-\-\s\w\>\/]*\>)
should work :)
I have been putting togethor an expression that needs to do something similar.
the finished product is:
/(?:((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)|(\/\*(?:(?!\*\/).|[\n\r])*\*\/)|(\/\/[^\n\r]*(?:[\n\r]+|$))|((?:=|:)\s*(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))|((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)[gimy]?\.(?:exec|test|match|search|replace|split)\()|(\.(?:exec|test|match|search|replace|split)\((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))|(<!--(?:(?!-->).)*-->))/g
Scary right?
To break it down, the first part matches anything within single or double quotation marks
This is necessary to avoid matching quoted strings
((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)
the second part matches multiline comments delimited by /* */
(\/\*(?:(?!\*\/).|[\n\r])*\*\/)
The third part matches single line comments starting anywhere in the line
(\/\/[^\n\r]*(?:[\n\r]+|$))
The fourth through sixth parts matchs anything within a regex literal
This relies on a preceding equals sign or the literal being before or after a regex call
((?:=|:)\s*(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))
((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)[gimy]?\.(?:exec|test|match|search|replace|split)\()
(\.(?:exec|test|match|search|replace|split)\((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))
and the seventh which I originally forgot removes the html comments
(<!--(?:(?!-->).)*-->)
I had an issue with my dev environment issuing errors for a regex that broke a line, so I used the following solution
var ADW_GLOBALS = new Object
ADW_GLOBALS = {
quotations : /((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)/,
multiline_comment : /(\/\*(?:(?!\*\/).|[\n\r])*\*\/)/,
single_line_comment : /(\/\/[^\n\r]*[\n\r]+)/,
regex_literal : /(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)/,
html_comments : /(<!--(?:(?!-->).)*-->)/,
regex_of_doom : ''
}
ADW_GLOBALS.regex_of_doom = new RegExp(
'(?:' + ADW_GLOBALS.quotations.source + '|' +
ADW_GLOBALS.multiline_comment.source + '|' +
ADW_GLOBALS.single_line_comment.source + '|' +
'((?:=|:)\\s*' + ADW_GLOBALS.regex_literal.source + ')|(' +
ADW_GLOBALS.regex_literal.source + '[gimy]?\\.(?:exec|test|match|search|replace|split)\\(' + ')|(' +
'\\.(?:exec|test|match|search|replace|split)\\(' + ADW_GLOBALS.regex_literal.source + ')|' +
ADW_GLOBALS.html_comments.source + ')' , 'g'
);
changed_text = code_to_test.replace(ADW_GLOBALS.regex_of_doom, function(match, $1, $2, $3, $4, $5, $6, $7, $8, offset, original){
if (typeof $1 != 'undefined') return $1;
if (typeof $5 != 'undefined') return $5;
if (typeof $6 != 'undefined') return $6;
if (typeof $7 != 'undefined') return $7;
return '';
}
This returns anything captured by the quoted string text and anything found in a regex literal intact but returns an empty string for all the comment captures.
I know this is excessive and rather difficult to maintain but it does appear to work for me so far.
This works for almost all cases:
var RE_BLOCKS = new RegExp([
/\/(\*)[^*]*\*+(?:[^*\/][^*]*\*+)*\//.source, // $1: multi-line comment
/\/(\/)[^\n]*$/.source, // $2 single-line comment
/"(?:[^"\\]*|\\[\S\s])*"|'(?:[^'\\]*|\\[\S\s])*'/.source, // - string, don't care about embedded eols
/(?:[$\w\)\]]|\+\+|--)\s*\/(?![*\/])/.source, // - division operator
/\/(?=[^*\/])[^[/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[/\\]*)*?\/[gim]*/.source
].join('|'), // - regex
'gm' // note: global+multiline with replace() need test
);
// remove comments, keep other blocks
function stripComments(str) {
return str.replace(RE_BLOCKS, function (match, mlc, slc) {
return mlc ? ' ' : // multiline comment (replace with space)
slc ? '' : // single/multiline comment
match; // divisor, regex, or string, return as-is
});
}
The code is based on regexes from jspreproc, I wrote this tool for the riot compiler.
See http://github.com/aMarCruz/jspreproc
In plain simple JS regex, this:
my_string_or_obj.replace(/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm, ' ')
a bit simpler -
this works also for multiline - (<!--.*?-->)|(<!--[\w\W\n\s]+?-->)
Simple regex ONLY for multi-lines:
/\*((.|\n)(?!/))+\*/
The accepted solution does not capture all common use cases. See examples here: https://regex101.com/r/38dIQk/1.
The following regular expression should match JavaScript comments more reliably:
/(?:\/\*(?:[^\*]|\**[^\*\/])*\*+\/)|(?:\/\/[\S ]*)/g
For demonstration, visit the following link: https://regex101.com/r/z99Nq5/1/.
This is late to be of much use to the original question, but maybe it will help someone.
Based on #Ryan Wheale's answer, I've found this to work as a comprehensive capture to ensure that matches exclude anything found inside a string literal.
/(?:\r\n|\n|^)(?:[^'"])*?(?:'(?:[^\r\n\\']|\\'|[\\]{2})*'|"(?:[^\r\n\\"]|\\"|[\\]{2})*")*?(?:[^'"])*?(\/\*(?:[\s\S]*?)\*\/|\/\/.*)/g
The last group (all others are discarded) is based on Ryan's answer. Example here.
This assumes code is well structured and valid javascript.
Note: this has not been tested on poorly structured code which may or may not be recoverable depending on the javascript engine's own heuristics.
Note: this should hold for valid javascript < ES6, however, ES6 allows multi-line string literals, in which case this regex will almost certainly break, though that case has not been tested.
However, it is still possible to match something that looks like a comment inside a regex literal (see comments/results in the Example above).
I use the above capture after replacing all regex literals using the following comprehensive capture extracted from es5-lexer here and here, as referenced in Mike Samuel's answer to this question:
/(?:(?:break|case|continue|delete|do|else|finally|in|instanceof|return|throw|try|typeof|void|[+]|-|[.]|[/]|,|[*])|[!%&(:;<=>?[^{|}~])?(\/(?![*/])(?:[^\\\[/\r\n\u2028\u2029]|\[(?:[^\]\\\r\n\u2028\u2029]|\\(?:[^\r\n\u2028\u2029ux]|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}))+\]|\\(?:[^\r\n\u2028\u2029ux]|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}))*\/[gim]*)/g
For completeness, see also this trivial caveat.
If you click on the link below you find a comment removal script written in regex.
These are 112 lines off code that work together also works with mootools and Joomla and drupal and other cms websites.
Tested it on 800.000 lines of code and comments. works fine.
This one also selects multiple parenthetical like ( abc(/nn/('/xvx/'))"// testing line") and comments that are between colons and protect them.
23-01-2016..! This is the code with the comments in it.!!!!
Click Here
I was looking for a quick Regex solution too, but none of the answers provided work 100%. Each one ends up breaking the source code in some way, mostly due to comments detected inside string literals. E.g.
var string = "https://www.google.com/";
Becomes
var string = "https:
For the benefit of those coming in from google, I ended up writing a short function (in Javascript) that achieves what the Regex couldn't do. Modify for whatever language you are using to parse Javascript.
function removeCodeComments(code) {
var inQuoteChar = null;
var inBlockComment = false;
var inLineComment = false;
var inRegexLiteral = false;
var newCode = '';
for (var i=0; i<code.length; i++) {
if (!inQuoteChar && !inBlockComment && !inLineComment && !inRegexLiteral) {
if (code[i] === '"' || code[i] === "'" || code[i] === '`') {
inQuoteChar = code[i];
}
else if (code[i] === '/' && code[i+1] === '*') {
inBlockComment = true;
}
else if (code[i] === '/' && code[i+1] === '/') {
inLineComment = true;
}
else if (code[i] === '/' && code[i+1] !== '/') {
inRegexLiteral = true;
}
}
else {
if (inQuoteChar && ((code[i] === inQuoteChar && code[i-1] != '\\') || (code[i] === '\n' && inQuoteChar !== '`'))) {
inQuoteChar = null;
}
if (inRegexLiteral && ((code[i] === '/' && code[i-1] !== '\\') || code[i] === '\n')) {
inRegexLiteral = false;
}
if (inBlockComment && code[i-1] === '/' && code[i-2] === '*') {
inBlockComment = false;
}
if (inLineComment && code[i] === '\n') {
inLineComment = false;
}
}
if (!inBlockComment && !inLineComment) {
newCode += code[i];
}
}
return newCode;
}
2019:
All other answers are incomplete and full of shortcomings. I take the time to write complete answer that WORK
function stripComments(code){
const savedText = [];
return code
.replace(/(['"`]).*?\1/gm,function (match) {
var i = savedText.push(match);
return (i-1)+'###';
})
// remove // comments
.replace(/\/\/.*/gm,'')
// now extract all regex and save them
.replace(/\/[^*\n].*\//gm,function (match) {
var i = savedText.push(match);
return (i-1)+'###';
})
// remove /* */ comments
.replace(/\/\*[\s\S]*\*\//gm,'')
// remove <!-- --> comments
.replace(/<!--[\s\S]*-->/gm, '')
.replace(/\d+###/gm,function(match){
var i = Number.parseInt(match);
return savedText[i];
})
}
var cleancode = stripComments(stripComments.toString())
console.log(cleancode)
Other answers not working on samples code like that:
// won't execute the creative code ("Can't execute code form a freed script"),
navigator.userAgent.match(/\b(MSIE |Trident.*?rv:|Edge\/)(\d+)/);
function stripComments(code){
const savedText = [];
return code
// extract strings and regex
.replace(/(['"`]).*?\1/gm,function (match) {
savedText.push(match);
return '###';
})
// remove // comments
.replace(/\/\/.*/gm,'')
// now extract all regex and save them
.replace(/\/[^*\n].*\//gm,function (match) {
savedText.push(match);
return '###';
})
// remove /* */ comments
.replace(/\/\*[\s\S]*\*\//gm,'')
// remove <!-- --> comments
.replace(/<!--[\s\S]*-->/gm, '')
/*replace \ with \\ so we not lost \b && \t*/
.replace(/###/gm,function(){
return savedText.shift();
})
}
var cleancode = stripComments(stripComments.toString())
console.log(cleancode)
for /**/ and //
/(?:(?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:(?<!\:|\\\|\')\/\/.*))/gm
I wonder if this was a trick question given by
a professor to students. Why? Because it seems
to me it is IMPOSSIBLE to do this, with
Regular Expressions, in the general case.
Your (or whoever's code it is) can contain
valid JavaScript like this:
let a = "hello /* ";
let b = 123;
let c = "world */ ";
Now if you have a regexp which removes everything
between a pair of /* and */, it would break the code
above, it would remove the executable code in the
middle as well.
If you try to devise a regexp that would not
remove comments which contain quotes then
you cannot remove such comments. That applies
to single-quote, double-quotes and back-quotes.
You can not remove (all) comments with Regular
Expressions in JavaScript, it seems to me,
maybe someone can point out a way how to do
it for the case above.
What you can do is build a small parser which
goes through the code character by character
and knows when it is inside a string and when
it is inside a comment, and when it is inside
a comment inside a string and so on.
I'm sure there are good open source JavaScript
parsers that can do this. Maybe some of the
packaging and minifying tools can do this for
you as well.
For block comment:
https://regex101.com/r/aepSSj/1
Matches slash character (the \1) only if slash character is followed by asterisk.
(\/)(?=\*)
maybe followed by another asterisk
(?:\*)
followed by first group of match, or zero or more times from something...maybe, without remember the match but capture as a group.
((?:\1|[\s\S])*?)
followed by asterisk and first group
(?:\*)\1
For block and/or inline comment:
https://regex101.com/r/aepSSj/2
where | mean or and (?=\/\/(.*)) capture anything after any //
or https://regex101.com/r/aepSSj/3
to capture the third part too
all in: https://regex101.com/r/aepSSj/8
DEMO: https://onecompiler.com/javascript/3y825u3d5
const context = `
<html>
<script type="module">
/* I'm a comment */
/*
* I'm a comment aswell url="https://example.com/";
*/
var re = /\\/*not a comment!*/;
var m = /\\//.test("\"not a comment!\"");
var re = /"/; // " thiscommentishandledasascode!
const s1 = "multi String \\
\\"double quote\\" \\
// single commet in str \\
/* multiple lines commet in str \\
secend line */ \\
last line";
const s2 = 's2"s';
const url = "https://example.com/questions/5989315/";
let a = "hello /* ";
let b = 123;
let c = "world */ ";
//public static final String LETTERS_WORK_FOLDER = "/Letters/Generated/Work";
console.log(/*comment in
console.log*/ "!message at console.log");
function displayMsg( // the end comment
/*commet arg1*/ a, ...args) {
console.log("Hello World!", a, ...args)
}
<\/script>
<body>
<!-- HTML Comment //--> or <!-- HTML Comment -->
<!--
function displayMsg() {
alert("Hello World!")
}
//-->
</body>
</html>
`;
console.log("before:\n" + context);
console.log("<".repeat(100));
const save = {'txt':[], 'comment':[], 'regex': []};
const context2 =
context.replace(/(['"`]|\/[\*\/]{0,1}|<!\-\-)(?:(?=(?<=\/\*))[\s\S]*?\*\/|(?=(?<=\/\/)).*|(?=(?<=<!\-\-))[\s\S]*?\-\->|(?=(?<=[\s\=]\/)).+?(?<!\\)\/|(?=(?<=['"`]))[\s\S]*?(?<!\\)\1)/g,
function (m) {
const t = (m[0].match(/["'`]/) && 'txt') || (m.match(/^(\/\/|\/\*|<)/) && 'comment') || 'regex';
save[t].push(m);
return '${save.'+t+'['+(save[t].length - 1)+']}';
}).replace(/[\S\s]*/, function(m) {
console.log("watch:\n"+m);
console.log(">".repeat(100));
/*
##remove comment
save.comment = save.comment.map(_ => _.replace(/[\S\s]+/,""));
##replace comment
save.comment = save.comment.map(_ => _.replace(/console\.log/g, 'CONSOLE.LOG'));
##replace text
save.txt = save.txt.map(_ => _.replace(/console\.log/g, 'CONSOLE.LOG'));
##replace your code
m = m.replace(/console\.log/g, 'console.warn');
*/
// console.warn("##remove comment -> save.comment.fill('');");
save.comment.fill('');
return m;
}).replace(/\$\{save.(\w+)\[(\d+)\]\}/g, function(m, t, id) {
return save[t][id];
}).replace(/[\S\s]*/, function(m) {
console.log("result:", m);
// console.log("compare:", (context === m));
return m;
})
My English is not good, can someone help translate what I have written, I will be very grateful
Consider some problems
A.There may be strings in comments, or comments in strings, like
/*
const url="https://example.com/";
*/
const str = "i am s string and /*commet in string*/";
B. " or ' or ` in a string will be escaped with
like
const str = "my name is \"john\"";
const str2 = 'i am "john\'s" friend';
Combining the above multiple regex replaces will cause some problems
Consider regex find to the beginning part
" ' ` // /* <!--
use regex
(['"`]|\/[\*\/]|<!\-\-)
(['"`]|/[*/]|<!\-\-) result as \1
\1 is one of ' or " or
`
or /* or // or <!--
use If-Then-Else Conditionals in Regular Expressions
https://www.regular-expressions.info/conditional.html
(?:(?=(?<=\/\*))[\s\S]*?\*\/|(?=(?<=\/\/)).*|(?=(?<=<!\-\-))[\s\S]*?\-\->|[^\1]*?(?<!\\)\1)
if (?=(?<=\/\*))[\s\S]*?\*\/
(?=(?<=\/\*)) positive lookbehind (?<=\/\*) beacuse/*
It's a multi-line comment, so it should be followed by the latest one */
[\s\S]*?\*\/ match complete /*..\n..\n. */
elseif (?=(?<=\/\/)).*
(?=(?<=//)).* positive lookbehind
(?<=\/\/) catch // single line commet
.* match complete // any single commet
elseif (?=(?<=<!\-\-))[\s\S]*?\-\->
(?=(?<=<!--)) positive lookbehind (?<=<!\-\-) ,
[\s\S]*?\-\-> match complete
<!--..\n..\n. /*/*\-\->
else [^\1]*?(?<!\\)\1
Finally need to process the string
use regex [\s\S]*?\1
maybe the wrong result with "STR\" or 'STR"S\'
at [\s\S]*?we can use "positive lookbehind"
add this [\s\S]*?(?<!\\)\1 to filter escape quotes
end
Based on above attempts and using UltraEdit , mostly Abhishek Simon, I found this to work for inline comments and handles all of the characters within the comment.
(\s\/\/|$\/\/)[\w\s\W\S.]*
This matches comments at the start of the line or with a space before //
//public static final String LETTERS_WORK_FOLDER =
"/Letters/Generated/Work";
but not
"http://schemas.us.com.au/hub/'>" +
so it is only not good for something like
if(x){f(x)}//where f is some function
it just needs to be
if(x){f(x)} //where f is function

RegEx for match/replacing JavaScript comments (both multiline and inline)

I need to remove all JavaScript comments from a JavaScript source using the JavaScript RegExp object.
What I need is the pattern for the RegExp.
So far, I've found this:
compressed = compressed.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');
This pattern works OK for:
/* I'm a comment */
or for:
/*
* I'm a comment aswell
*/
But doesn't seem to work for the inline:
// I'm an inline comment
I'm not quite an expert for RegEx and it's patterns, so I need help.
Also, I' would like to have a RegEx pattern which would remove all those HTML-like comments.
<!-- HTML Comment //--> or <!-- HTML Comment -->
And also those conditional HTML comments, which can be found in various JavaScript sources.
Thanks.
NOTE: Regex is not a lexer or a parser. If you have some weird edge case where you need some oddly nested comments parsed out of a string, use a parser. For the other 98% of the time this regex should work.
I had pretty complex block comments going on with nested asterisks, slashes, etc. The regular expression at the following site worked like a charm:
http://upshots.org/javascript/javascript-regexp-to-remove-comments
(see below for original)
Some modifications have been made, but the integrity of the original regex has been preserved. In order to allow certain double-slash (//) sequences (such as URLs), you must use back reference $1 in your replacement value instead of an empty string. Here it is:
/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm
// JavaScript:
// source_string.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');
// PHP:
// preg_replace("/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/m", "$1", $source_string);
DEMO: https://regex101.com/r/B8WkuX/1
FAILING USE CASES: There are a few edge cases where this regex fails. An ongoing list of those cases is documented in this public gist. Please update the gist if you can find other cases.
...and if you also want to remove <!-- html comments --> use this:
/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*|<!--[\s\S]*?-->$/
(original - for historical reference only)
// DO NOT USE THIS - SEE ABOVE
/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm
try this,
(\/\*[\w\'\s\r\n\*]*\*\/)|(\/\/[\w\s\']*)|(\<![\-\-\s\w\>\/]*\>)
should work :)
I have been putting togethor an expression that needs to do something similar.
the finished product is:
/(?:((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)|(\/\*(?:(?!\*\/).|[\n\r])*\*\/)|(\/\/[^\n\r]*(?:[\n\r]+|$))|((?:=|:)\s*(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))|((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)[gimy]?\.(?:exec|test|match|search|replace|split)\()|(\.(?:exec|test|match|search|replace|split)\((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))|(<!--(?:(?!-->).)*-->))/g
Scary right?
To break it down, the first part matches anything within single or double quotation marks
This is necessary to avoid matching quoted strings
((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)
the second part matches multiline comments delimited by /* */
(\/\*(?:(?!\*\/).|[\n\r])*\*\/)
The third part matches single line comments starting anywhere in the line
(\/\/[^\n\r]*(?:[\n\r]+|$))
The fourth through sixth parts matchs anything within a regex literal
This relies on a preceding equals sign or the literal being before or after a regex call
((?:=|:)\s*(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))
((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)[gimy]?\.(?:exec|test|match|search|replace|split)\()
(\.(?:exec|test|match|search|replace|split)\((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))
and the seventh which I originally forgot removes the html comments
(<!--(?:(?!-->).)*-->)
I had an issue with my dev environment issuing errors for a regex that broke a line, so I used the following solution
var ADW_GLOBALS = new Object
ADW_GLOBALS = {
quotations : /((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)/,
multiline_comment : /(\/\*(?:(?!\*\/).|[\n\r])*\*\/)/,
single_line_comment : /(\/\/[^\n\r]*[\n\r]+)/,
regex_literal : /(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)/,
html_comments : /(<!--(?:(?!-->).)*-->)/,
regex_of_doom : ''
}
ADW_GLOBALS.regex_of_doom = new RegExp(
'(?:' + ADW_GLOBALS.quotations.source + '|' +
ADW_GLOBALS.multiline_comment.source + '|' +
ADW_GLOBALS.single_line_comment.source + '|' +
'((?:=|:)\\s*' + ADW_GLOBALS.regex_literal.source + ')|(' +
ADW_GLOBALS.regex_literal.source + '[gimy]?\\.(?:exec|test|match|search|replace|split)\\(' + ')|(' +
'\\.(?:exec|test|match|search|replace|split)\\(' + ADW_GLOBALS.regex_literal.source + ')|' +
ADW_GLOBALS.html_comments.source + ')' , 'g'
);
changed_text = code_to_test.replace(ADW_GLOBALS.regex_of_doom, function(match, $1, $2, $3, $4, $5, $6, $7, $8, offset, original){
if (typeof $1 != 'undefined') return $1;
if (typeof $5 != 'undefined') return $5;
if (typeof $6 != 'undefined') return $6;
if (typeof $7 != 'undefined') return $7;
return '';
}
This returns anything captured by the quoted string text and anything found in a regex literal intact but returns an empty string for all the comment captures.
I know this is excessive and rather difficult to maintain but it does appear to work for me so far.
This works for almost all cases:
var RE_BLOCKS = new RegExp([
/\/(\*)[^*]*\*+(?:[^*\/][^*]*\*+)*\//.source, // $1: multi-line comment
/\/(\/)[^\n]*$/.source, // $2 single-line comment
/"(?:[^"\\]*|\\[\S\s])*"|'(?:[^'\\]*|\\[\S\s])*'/.source, // - string, don't care about embedded eols
/(?:[$\w\)\]]|\+\+|--)\s*\/(?![*\/])/.source, // - division operator
/\/(?=[^*\/])[^[/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[/\\]*)*?\/[gim]*/.source
].join('|'), // - regex
'gm' // note: global+multiline with replace() need test
);
// remove comments, keep other blocks
function stripComments(str) {
return str.replace(RE_BLOCKS, function (match, mlc, slc) {
return mlc ? ' ' : // multiline comment (replace with space)
slc ? '' : // single/multiline comment
match; // divisor, regex, or string, return as-is
});
}
The code is based on regexes from jspreproc, I wrote this tool for the riot compiler.
See http://github.com/aMarCruz/jspreproc
In plain simple JS regex, this:
my_string_or_obj.replace(/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm, ' ')
a bit simpler -
this works also for multiline - (<!--.*?-->)|(<!--[\w\W\n\s]+?-->)
Simple regex ONLY for multi-lines:
/\*((.|\n)(?!/))+\*/
The accepted solution does not capture all common use cases. See examples here: https://regex101.com/r/38dIQk/1.
The following regular expression should match JavaScript comments more reliably:
/(?:\/\*(?:[^\*]|\**[^\*\/])*\*+\/)|(?:\/\/[\S ]*)/g
For demonstration, visit the following link: https://regex101.com/r/z99Nq5/1/.
This is late to be of much use to the original question, but maybe it will help someone.
Based on #Ryan Wheale's answer, I've found this to work as a comprehensive capture to ensure that matches exclude anything found inside a string literal.
/(?:\r\n|\n|^)(?:[^'"])*?(?:'(?:[^\r\n\\']|\\'|[\\]{2})*'|"(?:[^\r\n\\"]|\\"|[\\]{2})*")*?(?:[^'"])*?(\/\*(?:[\s\S]*?)\*\/|\/\/.*)/g
The last group (all others are discarded) is based on Ryan's answer. Example here.
This assumes code is well structured and valid javascript.
Note: this has not been tested on poorly structured code which may or may not be recoverable depending on the javascript engine's own heuristics.
Note: this should hold for valid javascript < ES6, however, ES6 allows multi-line string literals, in which case this regex will almost certainly break, though that case has not been tested.
However, it is still possible to match something that looks like a comment inside a regex literal (see comments/results in the Example above).
I use the above capture after replacing all regex literals using the following comprehensive capture extracted from es5-lexer here and here, as referenced in Mike Samuel's answer to this question:
/(?:(?:break|case|continue|delete|do|else|finally|in|instanceof|return|throw|try|typeof|void|[+]|-|[.]|[/]|,|[*])|[!%&(:;<=>?[^{|}~])?(\/(?![*/])(?:[^\\\[/\r\n\u2028\u2029]|\[(?:[^\]\\\r\n\u2028\u2029]|\\(?:[^\r\n\u2028\u2029ux]|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}))+\]|\\(?:[^\r\n\u2028\u2029ux]|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}))*\/[gim]*)/g
For completeness, see also this trivial caveat.
If you click on the link below you find a comment removal script written in regex.
These are 112 lines off code that work together also works with mootools and Joomla and drupal and other cms websites.
Tested it on 800.000 lines of code and comments. works fine.
This one also selects multiple parenthetical like ( abc(/nn/('/xvx/'))"// testing line") and comments that are between colons and protect them.
23-01-2016..! This is the code with the comments in it.!!!!
Click Here
I was looking for a quick Regex solution too, but none of the answers provided work 100%. Each one ends up breaking the source code in some way, mostly due to comments detected inside string literals. E.g.
var string = "https://www.google.com/";
Becomes
var string = "https:
For the benefit of those coming in from google, I ended up writing a short function (in Javascript) that achieves what the Regex couldn't do. Modify for whatever language you are using to parse Javascript.
function removeCodeComments(code) {
var inQuoteChar = null;
var inBlockComment = false;
var inLineComment = false;
var inRegexLiteral = false;
var newCode = '';
for (var i=0; i<code.length; i++) {
if (!inQuoteChar && !inBlockComment && !inLineComment && !inRegexLiteral) {
if (code[i] === '"' || code[i] === "'" || code[i] === '`') {
inQuoteChar = code[i];
}
else if (code[i] === '/' && code[i+1] === '*') {
inBlockComment = true;
}
else if (code[i] === '/' && code[i+1] === '/') {
inLineComment = true;
}
else if (code[i] === '/' && code[i+1] !== '/') {
inRegexLiteral = true;
}
}
else {
if (inQuoteChar && ((code[i] === inQuoteChar && code[i-1] != '\\') || (code[i] === '\n' && inQuoteChar !== '`'))) {
inQuoteChar = null;
}
if (inRegexLiteral && ((code[i] === '/' && code[i-1] !== '\\') || code[i] === '\n')) {
inRegexLiteral = false;
}
if (inBlockComment && code[i-1] === '/' && code[i-2] === '*') {
inBlockComment = false;
}
if (inLineComment && code[i] === '\n') {
inLineComment = false;
}
}
if (!inBlockComment && !inLineComment) {
newCode += code[i];
}
}
return newCode;
}
2019:
All other answers are incomplete and full of shortcomings. I take the time to write complete answer that WORK
function stripComments(code){
const savedText = [];
return code
.replace(/(['"`]).*?\1/gm,function (match) {
var i = savedText.push(match);
return (i-1)+'###';
})
// remove // comments
.replace(/\/\/.*/gm,'')
// now extract all regex and save them
.replace(/\/[^*\n].*\//gm,function (match) {
var i = savedText.push(match);
return (i-1)+'###';
})
// remove /* */ comments
.replace(/\/\*[\s\S]*\*\//gm,'')
// remove <!-- --> comments
.replace(/<!--[\s\S]*-->/gm, '')
.replace(/\d+###/gm,function(match){
var i = Number.parseInt(match);
return savedText[i];
})
}
var cleancode = stripComments(stripComments.toString())
console.log(cleancode)
Other answers not working on samples code like that:
// won't execute the creative code ("Can't execute code form a freed script"),
navigator.userAgent.match(/\b(MSIE |Trident.*?rv:|Edge\/)(\d+)/);
function stripComments(code){
const savedText = [];
return code
// extract strings and regex
.replace(/(['"`]).*?\1/gm,function (match) {
savedText.push(match);
return '###';
})
// remove // comments
.replace(/\/\/.*/gm,'')
// now extract all regex and save them
.replace(/\/[^*\n].*\//gm,function (match) {
savedText.push(match);
return '###';
})
// remove /* */ comments
.replace(/\/\*[\s\S]*\*\//gm,'')
// remove <!-- --> comments
.replace(/<!--[\s\S]*-->/gm, '')
/*replace \ with \\ so we not lost \b && \t*/
.replace(/###/gm,function(){
return savedText.shift();
})
}
var cleancode = stripComments(stripComments.toString())
console.log(cleancode)
for /**/ and //
/(?:(?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:(?<!\:|\\\|\')\/\/.*))/gm
I wonder if this was a trick question given by
a professor to students. Why? Because it seems
to me it is IMPOSSIBLE to do this, with
Regular Expressions, in the general case.
Your (or whoever's code it is) can contain
valid JavaScript like this:
let a = "hello /* ";
let b = 123;
let c = "world */ ";
Now if you have a regexp which removes everything
between a pair of /* and */, it would break the code
above, it would remove the executable code in the
middle as well.
If you try to devise a regexp that would not
remove comments which contain quotes then
you cannot remove such comments. That applies
to single-quote, double-quotes and back-quotes.
You can not remove (all) comments with Regular
Expressions in JavaScript, it seems to me,
maybe someone can point out a way how to do
it for the case above.
What you can do is build a small parser which
goes through the code character by character
and knows when it is inside a string and when
it is inside a comment, and when it is inside
a comment inside a string and so on.
I'm sure there are good open source JavaScript
parsers that can do this. Maybe some of the
packaging and minifying tools can do this for
you as well.
For block comment:
https://regex101.com/r/aepSSj/1
Matches slash character (the \1) only if slash character is followed by asterisk.
(\/)(?=\*)
maybe followed by another asterisk
(?:\*)
followed by first group of match, or zero or more times from something...maybe, without remember the match but capture as a group.
((?:\1|[\s\S])*?)
followed by asterisk and first group
(?:\*)\1
For block and/or inline comment:
https://regex101.com/r/aepSSj/2
where | mean or and (?=\/\/(.*)) capture anything after any //
or https://regex101.com/r/aepSSj/3
to capture the third part too
all in: https://regex101.com/r/aepSSj/8
DEMO: https://onecompiler.com/javascript/3y825u3d5
const context = `
<html>
<script type="module">
/* I'm a comment */
/*
* I'm a comment aswell url="https://example.com/";
*/
var re = /\\/*not a comment!*/;
var m = /\\//.test("\"not a comment!\"");
var re = /"/; // " thiscommentishandledasascode!
const s1 = "multi String \\
\\"double quote\\" \\
// single commet in str \\
/* multiple lines commet in str \\
secend line */ \\
last line";
const s2 = 's2"s';
const url = "https://example.com/questions/5989315/";
let a = "hello /* ";
let b = 123;
let c = "world */ ";
//public static final String LETTERS_WORK_FOLDER = "/Letters/Generated/Work";
console.log(/*comment in
console.log*/ "!message at console.log");
function displayMsg( // the end comment
/*commet arg1*/ a, ...args) {
console.log("Hello World!", a, ...args)
}
<\/script>
<body>
<!-- HTML Comment //--> or <!-- HTML Comment -->
<!--
function displayMsg() {
alert("Hello World!")
}
//-->
</body>
</html>
`;
console.log("before:\n" + context);
console.log("<".repeat(100));
const save = {'txt':[], 'comment':[], 'regex': []};
const context2 =
context.replace(/(['"`]|\/[\*\/]{0,1}|<!\-\-)(?:(?=(?<=\/\*))[\s\S]*?\*\/|(?=(?<=\/\/)).*|(?=(?<=<!\-\-))[\s\S]*?\-\->|(?=(?<=[\s\=]\/)).+?(?<!\\)\/|(?=(?<=['"`]))[\s\S]*?(?<!\\)\1)/g,
function (m) {
const t = (m[0].match(/["'`]/) && 'txt') || (m.match(/^(\/\/|\/\*|<)/) && 'comment') || 'regex';
save[t].push(m);
return '${save.'+t+'['+(save[t].length - 1)+']}';
}).replace(/[\S\s]*/, function(m) {
console.log("watch:\n"+m);
console.log(">".repeat(100));
/*
##remove comment
save.comment = save.comment.map(_ => _.replace(/[\S\s]+/,""));
##replace comment
save.comment = save.comment.map(_ => _.replace(/console\.log/g, 'CONSOLE.LOG'));
##replace text
save.txt = save.txt.map(_ => _.replace(/console\.log/g, 'CONSOLE.LOG'));
##replace your code
m = m.replace(/console\.log/g, 'console.warn');
*/
// console.warn("##remove comment -> save.comment.fill('');");
save.comment.fill('');
return m;
}).replace(/\$\{save.(\w+)\[(\d+)\]\}/g, function(m, t, id) {
return save[t][id];
}).replace(/[\S\s]*/, function(m) {
console.log("result:", m);
// console.log("compare:", (context === m));
return m;
})
My English is not good, can someone help translate what I have written, I will be very grateful
Consider some problems
A.There may be strings in comments, or comments in strings, like
/*
const url="https://example.com/";
*/
const str = "i am s string and /*commet in string*/";
B. " or ' or ` in a string will be escaped with
like
const str = "my name is \"john\"";
const str2 = 'i am "john\'s" friend';
Combining the above multiple regex replaces will cause some problems
Consider regex find to the beginning part
" ' ` // /* <!--
use regex
(['"`]|\/[\*\/]|<!\-\-)
(['"`]|/[*/]|<!\-\-) result as \1
\1 is one of ' or " or
`
or /* or // or <!--
use If-Then-Else Conditionals in Regular Expressions
https://www.regular-expressions.info/conditional.html
(?:(?=(?<=\/\*))[\s\S]*?\*\/|(?=(?<=\/\/)).*|(?=(?<=<!\-\-))[\s\S]*?\-\->|[^\1]*?(?<!\\)\1)
if (?=(?<=\/\*))[\s\S]*?\*\/
(?=(?<=\/\*)) positive lookbehind (?<=\/\*) beacuse/*
It's a multi-line comment, so it should be followed by the latest one */
[\s\S]*?\*\/ match complete /*..\n..\n. */
elseif (?=(?<=\/\/)).*
(?=(?<=//)).* positive lookbehind
(?<=\/\/) catch // single line commet
.* match complete // any single commet
elseif (?=(?<=<!\-\-))[\s\S]*?\-\->
(?=(?<=<!--)) positive lookbehind (?<=<!\-\-) ,
[\s\S]*?\-\-> match complete
<!--..\n..\n. /*/*\-\->
else [^\1]*?(?<!\\)\1
Finally need to process the string
use regex [\s\S]*?\1
maybe the wrong result with "STR\" or 'STR"S\'
at [\s\S]*?we can use "positive lookbehind"
add this [\s\S]*?(?<!\\)\1 to filter escape quotes
end
Based on above attempts and using UltraEdit , mostly Abhishek Simon, I found this to work for inline comments and handles all of the characters within the comment.
(\s\/\/|$\/\/)[\w\s\W\S.]*
This matches comments at the start of the line or with a space before //
//public static final String LETTERS_WORK_FOLDER =
"/Letters/Generated/Work";
but not
"http://schemas.us.com.au/hub/'>" +
so it is only not good for something like
if(x){f(x)}//where f is some function
it just needs to be
if(x){f(x)} //where f is function

Categories