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 communitySince 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 sed
:
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 sed
)
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
:
sed -e '/^$/d'
In summary,
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 (awk
or perl
one-liners) instead of sed
, such as:
perl -0pe 's/<!-- my comment -->.*?<!-- \/my comment end -->//gs' my_file