在unix中提取与模式匹配的所有子字符串
我在文本文件中有一个字符串,如下所示在unix中提取与模式匹配的所有子字符串,unix,sed,Unix,Sed,我在文本文件中有一个字符串,如下所示 <sample:Recipients><sample:user name="11111111" guid="8fa4fbaabf904a16ad65449bd7adcba1"/><sample:user name="22222222" guid="f74ebd3310834601a2c22a5dde33c02a"/><sample:user name="33333333" guid="5fcd2e7775cb42ec
<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'
grep-o.“*”sample.txt“| sed-n's/*\([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\)./\1/p”
但我只得到最后一个值
33333333
。如何从所有用户标记中提取值?您可以使用以下快速且肮脏的grep
命令来实现您的目标:
$ grep -E 'sample:Recipients>|<sample:user' file | grep -oP '(?<=name=")[^"]*'
解释:
$ 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
仅当匹配模式时才使用sed
和处理行name=
,然后通过对名称值的反向引用替换整行:\1
(属性值)
好的解决方案:
$ 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
不要使用grepping或sed
只需使用xml解析器分析xml输出:
$ 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
$cat extract\u name.xsl
;
$xsltproc extract_name.xsl/dev/null
******1
*******2
*******3
这是最安全的工作方式,请注意,
2>/dev/null
用于忽略名称空间警告,因为未正确定义示例名称空间 以下单曲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
您可以尝试此
awk
script”:
awk-vrs='''-vfs='[a-z]+='{gsub([\']”),打印$2,$3}
记录分隔符RS设置为获取
之间的所有内容。字段分离器设置为捕捉符号的左侧部分=
gsub
命令去掉了双引号和额外的空格
print语句正在显示名称和guid。如果您不需要guid,请在
打印语句中删除,$3
。现在也请在您的帖子中的代码标签中提及预期输出。预期输出是什么?此外,基于此,您应该阅读以下内容:预期输出是值列表11111111
2222222
33333333
。感谢您的回复。我已经测试过,它可以正常工作。我们也可以使用sed吗?@Allan我认为sed部分不起作用,因为OP更改了示例文件格式。@JamesBrown:谢谢James,我确实需要编辑我的答案,同时我使用XML解析添加了一个更好的答案;-)不知道xsltproc,但它似乎更简单xmlstarlet sel-t-v'/@name'ip.txt 2>/dev/null
@Sundeep:非常感谢!我将查看此命令;-)尼斯awk
照常回答+1;-)@艾伦,谢谢艾伦,你太棒了,伙计,一如既往:)