给定具有以下内容的文件:
<root> <a></a> <b></b> </root>
该命令应输出:
<root> <a></a> <b></b>
我尝试过使用sed
的GNU Win32
端口:
删除最后两行。
这很快,但是假设</root>
是倒数第二行,如果不是,则会导致一个错误。
sed -e '$d' test.xml | sed -e '$d'
将所有</root>
replace为空string。
这可以工作,但比第一个解决scheme慢,如果有嵌套的<root>
元素(不太可能),将会中断。
sed -e 's|</root>||' test.xml
我正在处理的文件可能很大,所以效率很重要。
有没有办法限制sed替代文件中的最后一个事件? 或者还有其他一些效用会更快吗?
使用Perl和File :: Backwards应该是非常快的(相对的,我知道,但仍…)。 Perlfaq5有一个向后翻阅文件和删除行的主题。 您可以使用此主题的代码作为起点来检查您的模式。
用sed
:
sed -e ':a;N;$!ba;s|\(.*\)</root>\n\(.*\)|\1\2|'
如何使用awk
这个。
awk '/^<\/root>$/{next}/<\/root>/{sub(/<\/root>/,"");print;next}1' filename
First /pattern/{action}
语句只用 </root>
查找行。 它发现它,行动忽略它。
Second /pattern/{action}
语句在行中的任意位置查找包含</root>
的行。 如果模式发现它, sub function
替换它没有和打印行的其余部分。
对于所有没有模式</root>
的行,第一个是1
。 如果找到了,就打印出来。
我做了一个快速测试,这是结果 –
测试:
[jaypal:~/Temp] cat tmp <root> <a></a> <b></b> </root> <root> <a></a> <b></b> </root><root> <a></a> <b></b></root> [jaypal:~/Temp] awk '/^<\/root>$/{next}/<\/root>/{sub(/<\/root>/,"");print;next}1' tmp <root> <a></a> <b></b> <root> <a></a> <b></b> <root> <a></a> <b></b>
这也应该工作。 虽然它会删除所有</root>
而不是最后一个事件。
sed '/<\/root>/,$s///' filename
这可能适合你:
sed '/<\/root>/,/<root>/{/<\/root>/{h;d};H;//{x;p};${x;s/[^\n]*\n//p};d}' file
这假定每个<root>
标签都与一个关闭的</root>
标签相匹配,并且这些标签出现在不同的行上(如示例所示)。
说明:
</root>
标记和开始的<root>
标记或文件结束之间的行。 </root>
标签,请将其保存在保留空间(HS)中,然后将其删除并开始新的循环。 <root>
标签,交换到HS并打印出它的内容。 </root>
标签和文件的最后一行之间,则交换到HS,删除第一行,即关闭</root>
标签并打印剩下的部分。 有两个通行证的替代解决方案:
sed -n '/<\/root>/=' file | sed -n '$s/$/d/p' | sed -f - file
说明:
</root>
标签的行号 使用时间函数来查看哪一个是有效的。 sed应该是有效的。
$time command
在我看来,没有比grep更快的东西了。 尝试用awk index()来查看它是否更快。