This is what I came up with but it doesn't work with multiple lines:
sed -i '/<!-- my comment -->.*<!-- \/my comment end -->/d' my_file
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.Sign up to join this community
sed in its default mode operates on a line-by-line basis, an (admittedly obfuscated) approach would be to replace the newline characters with something else (such as the NULL character
\x00) before feeding the the content into
tr '\n' '\x00' <my_file
sed then sees the content as one line. However,
sed -e 's/<!-- my comment -->.*<!-- \/my comment end -->//'
will not work due to the greedy matching nature of
sed. We could implement a non-greedy match by matching everything inside the comment up to the first
< character, but this would work only if HTML comments were not allowed to contain
< characters (and, in particular, other HTML tags), which we cannot assume.
To solve this, we'll convert the sequence
<! to a single character not used elsewhere in the file, for which we can construct a non-greedy match. We'll choose the special character
\x01 for this purpose, which we convert back to
<! after the non-greedy match:
sed -e $'s/<!/\x01/g' -e $'s/\x01-- my comment -->[^\x01]*\x01-- \/my comment end -->//g'
(note the use of the shell syntax
$'' instead of
'' to pass the literal single-byte character \x01 to
In a third stage, the NULL characters are converted back into newlines:
tr '\x00' '\n'
And finally, empty lines are suppressed by another invocation of
sed -e '/^$/d'
tr '\n' '\x00' <my_file |sed -e $'s/<!/\x01/g' -e $'s/\x01-- my comment -->[^\x01]*\x01-- \/my comment end -->//g' |tr '\x00' '\n'|sed -e '/^$/d'
More elegant solutions exist if you choose to use different tools (
perl one-liners) instead of
sed, such as:
perl -0pe 's/<!-- my comment -->.*?<!-- \/my comment end -->//gs' my_file