如何使用sed删除*行首*处的<?xml?

Mic*_*ant 3 sed

我有一个文件,它的第一行以 <?xml

我可以使用 sed 删除它

/<\?xml/d
Run Code Online (Sandbox Code Playgroud)

但如果我尝试确保行开始 -

/^<\?xml/d
Run Code Online (Sandbox Code Playgroud)

它不匹配。
然而,其他线路如

<head ...
Run Code Online (Sandbox Code Playgroud)

被删除

/^<head/d
Run Code Online (Sandbox Code Playgroud)

我也试过

/^\<\?xml/d
Run Code Online (Sandbox Code Playgroud)

但没有匹配。

Joh*_*024 8

用:

sed '/^<?xml/d' filename
Run Code Online (Sandbox Code Playgroud)

在 GNU sed 下,\?表示零或前面的字符之一。(在 POSIX sed 中,\?是未定义的。)因为你想匹配一个文字?,让它不转义。

例子

让我们考虑这个测试文件:

$ cat filename
<?xml deleteme
<.xml keepme
..xml keepme
Run Code Online (Sandbox Code Playgroud)

上面的解决方案产生了所需的结果:

$ sed '/^<?xml/d' filename
<.xml keepme
..xml keepme
Run Code Online (Sandbox Code Playgroud)

问题中的第一个命令错误地不产生任何结果:

$ sed '/<\?xml/d' filename
$
Run Code Online (Sandbox Code Playgroud)

这是因为它匹配所有包含xml可选前缀的行<。由于所有行都包含xml,它们都被删除。

第二个命令不删除任何内容:

$ sed '/^<\?xml/d' filename
<?xml deleteme
<.xml keepme
..xml keepme
Run Code Online (Sandbox Code Playgroud)

这将删除任何线与零个或一个开始<,随后立即通过xml。由于每行在<和之间总是至少有一个字符xml,因此不会删除任何行。

有疑问时如何转义字符

如果您不确定某个字符是否处于正则表达式活动状态并且您想停用它,那么安全的做法是将其放在方括号中:

$ sed '/^[<][?]xml/d' filename
<.xml keepme
..xml keepme
Run Code Online (Sandbox Code Playgroud)

在 中[...],所有字符都被视为文字字符。


cuo*_*glm 5

在 POSIX基本正则表达式中, 的行为\?是未定义的(GNU sed 的其他一些转义序列是\|\+更多在这里)。

GNU sed 默认使用 BRE 并将这些转义序列视为特殊字符,含义\?与 相同?,匹配零个或一个字符。

所以<\?xml意味着零或一个<跟随xml,匹配<?xml对于 BRE,只有^, $, *, .,\[是特殊字符,因此如果您想匹配文字,请保留所有其他字符不变

sed -e '/^<?xml/d' <file
Run Code Online (Sandbox Code Playgroud)

如果您想坚持使用转义序列来匹配文字字符串,只需启用扩展正则表达式在下一版本中将成为 POSIX 标准):

sed -E '/^\?xml/d' <file
Run Code Online (Sandbox Code Playgroud)

sed -E使用 BSD sed)