我有一个文件,其第一行开头为<?xml
我可以使用 sed 删除它
/<\?xml/d
但如果我尝试确保线路开始 -
/^<\?xml/d
它不匹配。
然而其他线路,例如
<head ...
被删除
/^<head/d
我也尝试过
/^\<\?xml/d
但没有匹配。
答案1
使用:
sed '/^<?xml/d' filename
在 GNU sed 下,\?
表示零个或一个前面的字符。 (在 POSIX sed 中,\?
未定义。)由于您想要匹配文字?
,因此不要将其转义。
例子
让我们考虑这个测试文件:
$ cat filename
<?xml deleteme
<.xml keepme
..xml keepme
上面的解决方案产生了所需的结果:
$ sed '/^<?xml/d' filename
<.xml keepme
..xml keepme
问题中的第一个命令错误地不会产生任何结果:
$ sed '/<\?xml/d' filename
$
这是因为它匹配所有包含xml
可选前面的行<
。由于所有行都包含xml
,因此它们都被删除。
第二个命令不删除任何内容:
$ sed '/^<\?xml/d' filename
<?xml deleteme
<.xml keepme
..xml keepme
这将删除任何以零或一<
开头的行立即地经过xml
。由于各行在<
和之间始终至少有一个字符xml
,因此不会删除任何行。
当有疑问时如何转义字符
如果您不确定某个字符是否处于正则表达式活动状态并且想要停用它,安全的做法是将其放在方括号中:
$ sed '/^[<][?]xml/d' filename
<.xml keepme
..xml keepme
在 内部[...]
,所有字符都被视为文字字符。
答案2
在 POSIX 中基本正则表达式, 的行为\?
未定义(GNU sed 的其他一些转义序列是\|
,\+
等等这里)。
GNU sed 默认使用 BRE,它将这些转义序列视为特殊字符,含义\?
与 相同?
,匹配零个或一个字符。
所以<\?xml
意思是 0 或 1<
后面跟着xml
,匹配<?xml
。对于 BRE,只有^
, $
, *
, .
,\
和[
是特殊字符,所以如果您想匹配文字,请保持所有其他字符不变
sed -e '/^<?xml/d' <file
如果您想坚持使用转义序列来匹配文字字符串,只需启用扩展正则表达式(这将在下一版本中成为 POSIX 标准):
sed -E '/^\?xml/d' <file
(sed -E
与 BSD sed 一起使用)
答案3
我有一个文件,其第一行以
<?xml
[...] 开头,如果我尝试确保行首/^<\?xml/d
不匹配
文本前面可能有字节顺序标记 (BOM)。这些在 UTF-16 格式文件(特别是来自 Windows 系统的文件)中很常见,用于指示字节顺序文件中包含 16 位字符的字节数。
您可以使用众多十六进制转储工具之一(hex
、hexdump
、od -c
代表三个)并查看前几个字符来检查这一点。如果您看到FF FE
或FE FF
作为前两个字符,则它是 BOM。
由于保留 BOM 可能会更好,因此只需从 RE 中删除起始生产线要求即可最好地实现解决方案。
顺便说一句,如果您尝试从 XML 文件中提取数据,通常最好正确解析它,而不是使用 RE 挖掘它。 (当然也有例外,但我说的是一般情况,它允许对文件、注释结构等进行意外但有效的重新格式化。)
答案4
如果这是 xml 转换的结果(xsltprox foo.xsl bar.xml
例如),则 xml 行仅位于第一行。
使用以下任一方法:
awk 'NR>1'
当在管道中时,或者:
awk 'FNR>1' file1 file2 ... > result
具有多个文件。
sed -i -e 1d file1 file2 ...