我在文本文件中有一个字符串,如下所示。
messageBodyPart.setFileName("logo.png");
字符串是连续的,未格式化为正确的xml
我必须从标签中提取所有值
我使用了以下脚本
<sample:Recipients><sample:user name="11111111" guid="8fa4fbaabf904a16ad65449bd7adcba1"/><sample:user name="22222222" guid="f74ebd3310834601a2c22a5dde33c02a"/><sample:user name="33333333" guid="5fcd2e7775cb42ecbed5ac5dd85e1ca6"/></sample:Recipients>
但我只得到最后一个值grep -o "<sample:Recipients>.*</sample:Recipients>" "sample.txt"|sed -n 's/.*\([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\).*/\1/p'
。如何从所有用户标签中提取值?
答案 0 :(得分:2)
关注单awk
可能会对您有所帮助。
awk '
{
while(match($0,/sample:user name=\"[^"]*[0-9]+/)){
print substr($0,RSTART+18,RLENGTH-18);
$0=substr($0,RSTART+RLENGTH+1)}
}' Input_file
答案 1 :(得分:1)
您可以使用以下快速而脏的grep
命令来实现目标:
$ grep -E 'sample:Recipients>|<sample:user' file | grep -oP '(?<=name=")[^"]*'
<强> INPUT:强>
$ cat file
abc
abc1
<sample:Recipients>
<sample:user name="******1" guid="8fa4fbaabf904a16ad65449bd7adcba1"/>
<sample:user name="*******2" guid="f74ebd3310834601a2c22a5dde33c02a"/>
<sample:user name="*******3" guid="5fcd2e7775cb42ecbed5ac5dd85e1ca6"/>
</sample:Recipients>
abc2
abc
<强>输出:强>
$ grep -E 'sample:Recipients>|<sample:user' file | grep -oP '(?<=name=")[^"]*'
******1
*******2
*******3
<强>说明:强>
第一个grep
将获取包含您要从输入文件中隔离的XML的行,第二个将使用{{1}从名为name
的属性中选择值具有正面观察力的正则表达式perl
。
使用(?<=name=")[^"]*
的另一个快速而肮脏的解决方案:
sed
<强>说明:强>
您使用$ grep -E 'sample:Recipients>|<sample:user' file | sed -n '/name="/s/.*name="\([^"]*\)".*/\1/gp'
******1
*******2
*******3
并仅在匹配模式sed
时处理行,然后通过对名称值的反向引用替换整行:name=
(属性值)
良好的解决方案:
而不是grepping或使用\1
只需使用xml解析器来分析你的xml输出:
sed
这是最安全的工作方式,请注意$ cat extract_name.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declation="yes" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="/*/*/@name">
<xsl:value-of select="."/><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
$ xsltproc extract_name.xsl <(grep -E 'sample:Recipients>|<sample:user' file) 2>/dev/null
******1
*******2
*******3
用于忽略命名空间警告,因为未正确定义样本命名空间。
答案 2 :(得分:0)
您可以试试这个awk
脚本“:
awk -v RS='<[a-z:]+|/>' -v FS='[a-z]+=' '{gsub("[\" ]",""); print $2,$3}'
记录分隔符RS设置为在<...\>
之间获取所有内容。字段separtor设置为捕获符号=
的左侧部分。
gsub
命令摆脱了双引号和额外空格。
print语句显示名称和guid。如果您不需要guid,请删除,$3
声明中的print
。