Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在unix中提取与模式匹配的所有子字符串_Unix_Sed - Fatal编程技术网

在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>&#xa;</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;-)@艾伦,谢谢艾伦,你太棒了,伙计,一如既往:)