您好我是批处理文件的新手。
我正在处理批处理文件以从XML文件中删除行,例如C:\NewFile\ABC.xml
应该从文件内容中删除第二次出现标记到最后一次出现之后的所有内容。
ABC.xml
查看示例如下:
tag1
tag2......some text....../tag2
tag2......some text....../tag2
tag2......some text....../tag2
tag2......some text....../tag2
tag2......some text....../tag2
tag2......some text....../tag2
/tag1
期望的输出:
tag1
tag2......some text....../tag2
tag2......some text....../tag2
/tag1
有人可以帮我吗?
答案 0 :(得分:0)
我建议使用功能强大的文本编辑器和Perl正则表达式替换支持,如UltraEdit,Notepad ++,Sublime Text等。
使用
运行Perl正则表达式从文件顶部全部替换^((?:.*?tag2[\s\S]*?/tag2.*\r?\n){2})(?:.*?tag2[\s\S]*?/tag2.*\r?\n)+
作为搜索字符串,\1
作为替换字符串。
说明:
^
...在一行开头搜索。
(
... )
...是一个标记组。由此标记组内的表达式找到的字符串可以在搜索或替换字符串中反向引用。在此搜索字符串中有1个标记组,在替换字符串中以\1
反向引用,以保留前2个tag2
元素并删除所有其他元素。
(?:
... )
...是非标记组。非标记组通常用于OR表达式,或者此处用于此搜索字符串,以将乘数应用于{2}
和+
等表达式。
.*?
...找到除换行符之外的任何字符0次或更多次非贪婪。非贪婪意味着在第一次出现下一个固定字符串tag2
的字符串时停止匹配除换行符之外的任何字符。
[\s\S]*?
...匹配任何空白字符或任何非空格字符0次或更多次非贪婪。换句话说,[\s\S]
也匹配换行符,因为.
默认不匹配(除了使用特殊标志)。要匹配的下一个固定字符串是/tag2
。
.*
...找到除换行符之外的任何字符0次或更多次现在贪婪,这意味着直到行尾。
\r?\n
...可选择匹配回车符和换行符。所以XML文件可以是一个DOS / Windows文件,带有回车加行换行或Unix文件,只有换行作为行终止符。
{2}
...表示对于肯定匹配,非标记组中的表达式必须恰好应用2次。那些2"线"标记组中的表达式可以找到tag2
... /tag2
,因此替换字符串中的\1
只会保持替换状态。
匹配tag2
... /tag2
的表达式再次用于具有乘数+
的非标记组,这意味着1次或更多次。搜索字符串的第二部分找到的所有内容都将在替换时删除。
答案 1 :(得分:0)
您确实应该使用旨在解析和操作xml的实用程序或库。
在紧要关头,您可以使用我的JREPL.BAT utility that is able to do sophisticated regular expression replacements。但是如果你想要一个强大的xml处理解决方案,正则表达式真的不好。
JREPL.BAT是一个混合JScript /批处理脚本,可以在XP以后的任何Windows机器上本机运行。
您的方案缺少一些关键细节。
<tag2>
中是否始终包含<tag1>
?或外部标签无关紧要?首先,我假设您只想删除第二个之后的所有<tag2>
,无论它们出现在何处。
我将使用您related SuperUser question
中的ABC.xml示例<强> ABC.xml 强>
<tag1>
<tag2>...... Once upon a midnight dreary, ......</tag2>
<tag2>...... while I pondered, weak and weary, ......</tag2>
<tag2>...... Over many a quaint and curious ......</tag2>
<tag2>...... volume of forgotten lore— ......</tag2>
<tag2>...... While I nodded, nearly napping, ......</tag2>
<tag2>...... suddenly there came a tapping, ......</tag2>
︙
</tag1>
解决方案相当直接(注意 - 我对xml文档的布局做了很多可能不安全的假设。你最好使用专门设计用于处理xml的工具)。我假设你想要覆盖原始文件。
jrepl "<tag2>.*?</tag2>\s*" "++cnt>2?'':$0" /m /j /jbeg "cnt=0" /f ABC.xml /o -
/F filename
选项指定输入文件/O -
指定输出覆盖原始/M
选项指定多行模式,允许搜索换行符,从而使我能够删除整行。/J
选项将替换字符串视为JScript表达式/JBEG
选项初始化用于计算找到的代码数量的cnt
变量<tag2>...</tag2>
以及任何尾随空格。输出
<tag1>
<tag2>...... Once upon a midnight dreary, ......</tag2>
<tag2>...... while I pondered, weak and weary, ......</tag2>
</tag1>
现在我会让问题变得有点棘手。我将添加第二个<tag1>
,并假设您希望计数器在每个<tag1>
的开头重置为零。我还添加了另一个标签,表明它不会影响计数器。
<强> XYZ.xml 强>
<tag1>
<tag2>...... Once upon a midnight dreary, ......</tag2>
<tag2>...... while I pondered, weak and weary, ......</tag2>
<tag2>...... Over many a quaint and curious ......</tag2>
<tag2>...... volume of forgotten lore— ......</tag2>
<tag2>...... While I nodded, nearly napping, ......</tag2>
<tag2>...... suddenly there came a tapping, ......</tag2>
?
</tag1>
<tag1>
<tag2>Humpty Dumpty sat on a wall</tag2>
<someOtherTag>1</someOtherTag>
<tag2>Humpty Dumpty had a great fall</tag2>
<someOtherTag>2</someOtherTag>
<tag2>All the king's horses, and all the king's men</tag2>
<someOtherTag>3</someOtherTag>
<tag2>Couldn't put Humpty together again</tag2>
<someOtherTag>4</someOtherTag>
<tag1>
解决方案非常相似,除了现在我使用/T
选项指定搜索和替换表达式的空格分隔列表。第一个搜索表达式匹配<tag1>
,替换值只是将计数器重置为0,而不修改值。第二个搜索表达式与之前的<tag2>...</tag2>
匹配,替换也像以前一样运行。我假设<tag1>
始终位于第一个<tag2>
之前,所以我不必担心通过/JBEG
声明和初始化计数器。
jrepl "<tag1> <tag2>.*?</tag2>\s*" "cnt=0;$0 ++cnt>2?'':$0" /t " " /m /j /f XYZ.xml /o -
这是输出:
<tag1>
<tag2>...... Once upon a midnight dreary, ......</tag2>
<tag2>...... while I pondered, weak and weary, ......</tag2>
?
</tag1>
<tag1>
<tag2>Humpty Dumpty sat on a wall</tag2>
<someOtherTag>1</someOtherTag>
<tag2>Humpty Dumpty had a great fall</tag2>
<someOtherTag>2</someOtherTag>
<someOtherTag>3</someOtherTag>
<someOtherTag>4</someOtherTag>
<tag1>
由于JREPL是一个批处理文件,如果要在另一个批处理脚本中使用它,则必须在命令前加上CALL。
使用JREPL /?
获取JREPL可用的所有选项的完整帮助。