2

There are tons of examples to do the conversion from C-style line comment to 1-line block comment. But I need to do the opposite: find a regex to replace multi-line block comment with line comments. From:

This text must not be touched
/*
This
is
random
text
*/
This text must not be touched

To

This text must not be touched
// This
// is
// random
// text
This text must not be touched

I was thinking if there's a way to represent "each line" concept in regex, then just add // in front of each line. Something like

\/\*\n(?:(.+)\n)+\*\/ -> // $1

But the greediness nature of the regex engine makes $1 just match the last line before */. I know Perl and other languages have some advanced regex features like recursion, but I need to do this in a standard engine. Is there any trick to accomplish this?

EDIT: To clarify, I'm looking for pure regex solution, not involving any programming language. Should be testable on sites like https://regex101.com/.

6
  • What is the environment, in which you can use only standard regular expressions? Commented Oct 2, 2020 at 18:19
  • 1
    Let's assume Javascript, like regex101.com Commented Oct 2, 2020 at 18:21
  • 1
    Use /\/\*([^]*?)\*\//g to match a comment block then replace each ^ with // Commented Oct 2, 2020 at 18:33
  • So you want to remove the /* */ and prepend the // in one match - replace? Commented Oct 2, 2020 at 18:51
  • Yes, Add // in front of each line within the original block, in one match replace. Commented Oct 2, 2020 at 18:58

2 Answers 2

2

If you are interested in a single regex pass in the modern JavaScript engine (and other regex engines supporting infinite length patterns in lookbehinds), you can use

/(?<=^(\/)\*(?:(?!^\/\*)[\s\S])*?\r?\n)(?=[\s\S]*?^\*\/)|(?:\r?\n)?(?:^\/\*|^\*\/)/gm

Replace with $1$1, see the regex demo.

Details

  • (?<=^(\/)\*(?:(?!^\/\*)[\s\S])*?\r?\n) - a positive lookbehind that matches a location that is immediately preceded with
    • ^(\/)\* - /* substring at the start of a line (with / captured into Group 1)
    • (?:(?!^\/\*)[\s\S])*? - any char, zero or more occurrences, as few as possible, not starting a /* char sequence that appears at the start of a line
    • \r?\n - a CRLF or LF ending
  • (?=[\s\S]*?^\*\/) - a positive lookahead that requires any 0 or more chars as few as possible followed with */ at the start of a line, immediately to the right of the current location
  • | - or
  • (?:\r?\n)? - an optional CRLF or LF linebreak
  • (?:^\/\*|^\*\/) - and then either /* or */ at the start of a line.
Sign up to request clarification or add additional context in comments.

8 Comments

So you use the capturing group in the lookbehind to be the replacement, because if you use // literally you would get // in the replacement for every match which is too much. And due to the alternation, group 1 can be empty so there is no replacement right?
@Thefourthbird Correct, the solution is tricky, the alternation does not let hardcode the replacement pattern. So, more a hack for this concrete scenario.
I was playing around to see how to solve it, but this is awesome. One technique to remember :-) ++
@WiktorStribiżew So if instead we need to prefix something like #/ or @@, this trick won't work, right? We are just lucky then. BTW, the first line in Details is a typo (lookbehind)?
Problem: if there are /* inside the block comment, they will be replaced as well.
|
1

As usual in such cases, two regular expressions—the second applied to the matches of the first—can do what one cannot achieve.

const txt = `This text must not be touched
/*
This
is
random
text
*/
This text must not be touched`;

const to1line = str => str.replace(
    /\/\*\s*(.*?)\s*\*\//gs,
    (_, comment) => comment.replace( /^/mg, '//')
);
console.log( to1line( txt ));

4 Comments

When I say Javascript, I meant the Javascript style regex. No code is allowed. Can you link a testable regex101.com instance?
I do not think that it can be done with one regular expression, due to variable number of lines, and therefore captures, in a multi-line comment. Even if somebody can, I think he shouldn't.
I can accept answer like "it is not possible because ..." if you are sure about that. You can keep the existing Javascript code here in case other people can use a code-based solution.
Wait some time, perhaps somebody will find a way.

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.