使用bash工具从xml中删除标记 问题:

使用bash工具从xml中删除标记 问题:,xml,bash,awk,sed,Xml,Bash,Awk,Sed,我有一个应用程序,可以创建以下格式的日志 2014-09-01 12: 01: 01.899;some app logs 2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>111</e></d><d><e>123</e></d><d><e>222</e></d&g

我有一个应用程序,可以创建以下格式的日志

2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>111</e></d><d><e>123</e></d><d><e>222</e></d><d><e>333</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
2014-09-0112:01:01.899;一些应用程序日志
2014-09-01 12: 01: 02,045;一些应用程序日志2;111123222333;一些应用程序日志3
2014-09-01 12: 01: 03,625;一些应用程序日志4
使用bash工具,我想删除所有没有后代
123

如此

2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>123</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
2014-09-0112:01:01.899;一些应用程序日志
2014-09-01 12: 01: 02,045;一些应用程序日志2;123;一些应用程序日志3
2014-09-01 12: 01: 03,625;一些应用程序日志4
我尝试使用awk和sed来实现这一点,但失败了。请帮助写一个脚本或其他工具,可以做到这一点的指示

信息(从评论中移动) 目前我有这样一个(我找到的最好的)解决方案。”


echo'2014-09-01 12:01:01.899;一些应用程序日志2014-09-01 12:01:02045;一些应用程序日志2;111123222333;一些应用程序日志3 2014-09-01 12:01:03625;一些应用程序日志4'| awk'{print'也许这个awk示例可以引导您走向正确的方向:

$ awk -F';' '{gsub("<d><e>[^0-9]*</e></d>", "", $3)} {print}' some.log
2014-09-01 12: 01: 01.899; And, some app logs
2014-09-01 12: 01: 02,045  And, some app logs2 <a><b><c><d><e>123456789</e></d></c></b></a> some app logs3
2014-09-01 12: 01: 03,625; And, some app logs4
$awk-F';“{gsub([^0-9]*”,”,$3)}{print}”some.log
2014-09-01 12:01:01.899;以及一些应用程序日志
2014-09-01 12:01:02045和,一些应用程序日志123456789一些应用程序日志3
2014-09-01 12:01:03625;以及一些应用程序日志4
说明
-F';”
字段分隔符是分号
gsub(“[^0-9]*”,“,$3)
如果标签
之间第3列中的数据不是数字,请执行全局替换尝试以下操作:

$ awk -v t="<d><e>123</e></d>" '{gsub(t,RS); gsub("<d><e>[^<]+</e></d>",""); gsub(RS,t)}1' file
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>123</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4

$awk-vt=“123”{gsub(t,RS);gsub(“[^您可以通过perl简单地实现这一点

$ perl -pe 's/<e>(?:(?!\b123\b).)*?<\/e>//g; s/<([^><]*)><\/\1>//g' file
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>123</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
示例:

$ cat file
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>111</e></d><d><e>123</e><e>1234</e><e>123:4</e></d><d><e>222</e></d><d><e>333</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
$cat文件
2014-09-01 12:01:01.899;一些应用程序日志
2014-09-01 12:01:02045;一些应用程序日志2;1111231234123:4222333;一些应用程序日志3
2014-09-01 12:01:03625;一些应用程序日志4

$perl-pe的/(?:(?!123)。*?)//g;s///g'文件
2014-09-01 12:01:01.899;一些应用程序日志
2014-09-01 12:01:02045;部分应用程序日志2;123;部分应用程序日志3
2014-09-01 12:01:03625;一些应用程序日志4

以下假设输入文本位于名为“test.log”的文件中,并且您希望以某种形式的解决方案将输入导入和导出(即使用cat“test.log”而不是将其指定为输入)

使用占位符值: 如果您试图使用正则表达式处理与要保留的模式非常相似的所有内容,则通常更容易首先将您不希望处理的文本更改为占位符值,该占位符值很容易与您希望处理的模式区分开来:

cat test.log | sed -e "s/Q/Qz/g" -e "s/<e>123<\/e>/Qa/g" -e "s/<e>[^<]*<\/e>//g" -e "s/Qa/<e>123<\/e>/g" -e "s/Qz/Q/g" -e "s/<[^e]>[^<]*<\/[^e]>;\?//g" -e "s///g" -e "s///g" -e "s///g" -e "s///g" -e "s///g"
选择使用未保证在输入数据中不存在的占位符是一种风险。除非您了解风险并已选择接受风险,否则不应这样做。当发现任何此类问题的人员将立即审查输出时,接受此类风险更为合理

感谢埃德·莫顿,他提醒我,我已经养成了在没有充分考虑的情况下接受风险的习惯

使用正则表达式定义某些内容不是: 逐个字符:

$ cat file
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>111</e></d><d><e>123</e><e>1234</e><e>123:4</e></d><d><e>222</e></d><d><e>333</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
由于模式“123”非常简单和精确,因此定义一个正则表达式来匹配除该字符串之外的所有内容相对容易。请注意,如果您试图从匹配中排除一个更复杂的模式,则这将变得更加复杂:

cat test.log | sed -e "s/<e>\(\|[^1<][^<]*\|1[^2<][^<]*\|12[^3<][^<]*\)<\/e>//g" -e "s/<[^e]>[^<]*<\/[^e]>;\?//g" -e "s///g" -e "s///g" -e "s///g" -e "s///g" -e "s///g"

cat test.log | sed-e“s/\(\\\\\\[^1您尝试了什么?您陷入了什么困境?请分享您的代码。另外,更改应用程序提供日志的方式不是更好吗?我尝试使用sed多行模式删除XML中不必要的部分:
cat test.log{print”“| sed'/^\s*$/d'| sed'/]*>/{x;s*///;x};{H;g;};/]*>123]*>/!d;/]*$/{p;x;s/*/;x;}
用这些信息编辑您的问题。在注释中编写代码是不实际的。任何时候您发现自己使用了超过s、g和p(带-n)的代码在sed中,您的方法是错误的。在20世纪70年代中期,当awk发明时,所有用于操作多行输入的sed命令都已过时。定义
bash工具
:Perl?Python?xpath?sed和awk only?gawk?多亏了您的回答,我发现我需要改进输入数据,以便更好地呈现我的问题。所有
标记都已完成数字数据,我只对一个特定的
123
感兴趣。符号
的名称是
分号
,而不是
点逗号
。使用sed临时将
foo
替换为输入中不存在的字符串的方法是:
sed-e's/a/aA/g'-e's/foo/aB/g'文件| dostuff | sed-e's/aB/foo/g'-e's/aA/a/g'
。如果需要,只需将
a
替换为字符串
foo
中不存在的字符即可。占位符字符串的复杂性取决于您对输入文本可能内容的了解。我想说明一个概念,而不是提供一个最低限度的解决方案。您的建议假设已知字符串输入中不存在的le字符,或短字符串“aA”不存在。我正在使用一个较长的字符串进行说明,该字符串不太可能存在于输入中。您对输入中不存在的内容了解得越多,中间字符串就越简单。如果已知某个字符不存在,则占位符可以是该字符。不,这些都不是真的。
aA
可以存在在输入中很好,字符
a
可以存在于输入中,等等。这些都不重要,无论输入文件包含什么,解决方案都会按原样工作。尝试一下,仔细想想。是的,你是对的。我响应太快了。
aA
变成
aAA
,然后又变回
aA
。对。The第一次替换只是确保之后输入文件中不会出现
aB
(或
aC
a%
或任何其他内容),因为ev
cat test.log | sed -e "s/Q/Qz/g" -e "s/<e>123<\/e>/Qa/g" -e "s/<e>[^<]*<\/e>//g" -e "s/Qa/<e>123<\/e>/g" -e "s/Qz/Q/g" -e "s/<[^e]>[^<]*<\/[^e]>;\?//g" -e "s///g" -e "s///g" -e "s///g" -e "s///g" -e "s///g"
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>111</e></d><d><e>123</e></d><d><e>222</e></d><d><e>333</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
2014-09-01 12: 01: 04,045;some app logs5;<a><b><c><d><e>111</e></d><d><e>222</e></d><d><e>333</e></d></c></b></a>;some app logs6
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>111</e></d><d>Qa</d><d><e>222</e></d><d><e>333</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
2014-09-01 12: 01: 04,045;some app logs5;<a><b><c><d><e>111</e></d><d><e>222</e></d><d><e>333</e></d></c></b></a>;some app logs6
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d></d><d>Qa</d><d></d><d></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
2014-09-01 12: 01: 04,045;some app logs5;<a><b><c><d></d><d></d><d></d></c></b></a>;some app logs6
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d></d><d><e>123</e></d><d></d><d></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
2014-09-01 12: 01: 04,045;some app logs5;<a><b><c><d></d><d></d><d></d></c></b></a>;some app logs6
2014-09-01 12: 01: 01.899;some app logs
2014-09-01 12: 01: 02,045;some app logs2;<a><b><c><d><e>123</e></d></c></b></a>;some app logs3
2014-09-01 12: 01: 03,625;some app logs4
2014-09-01 12: 01: 04,045;some app logs5;some app logs6
cat test.log | sed -e "s/<e>123<\/e>/lOnG3Rep5LacEN2eV7E9rE4xIST/g" -e "s/<e>[^<]*<\/e>//g" -e "s/lOnG3Rep5LacEN2eV7E9rE4xIST/<e>123<\/e>/g" -e "s/<[^e]>[^<]*<\/[^e]>;\?//g" -e "s///g" -e "s///g" -e "s///g" -e "s///g" -e "s///g"
cat test.log | sed -e "s/<e>\(\|[^1<][^<]*\|1[^2<][^<]*\|12[^3<][^<]*\)<\/e>//g" -e "s/<[^e]>[^<]*<\/[^e]>;\?//g" -e "s///g" -e "s///g" -e "s///g" -e "s///g" -e "s///g"