【问题标题】:How to extract text from a file which appears one or more times in each line?如何从每行出现一次或多次的文件中提取文本?
【发布时间】:2013-07-20 17:57:30
【问题描述】:

我有一个文本文件,每行有 1 个或多个电子邮件 ID。例如

id:123, name:test, id: 5678, name john, address:new york  
id:567, name:bob  
id:3643, name:meg, id: 6721, name kate, address:la  

现在,问题是 id:value 可能在一行中出现一次或多次。如何提取所有 id:value 对以便输出为,

id:123, id:5678  
id:567  
id:3643, id:6721  

我尝试了egrep -o,但这是将每个id:value 对放在单独的行中。

sed/awk 应该可以解决问题,但我是菜鸟

不想使用Perl,因为这需要安装 Perl。

编辑: 在对数据文件的进一步分析中,我发现分隔符不一致,即并非所有行都是, 分隔的。有些甚至用:| 分隔。此外,, 出现在地址值字段中。即address:52nd st, new york。这可以在awk 中使用正则表达式完成吗?

【问题讨论】:

    标签: unix sed awk grep


    【解决方案1】:

    如果您的内容在文件test.txt 中,则使用以下命令:

    cat test.txt | sed 's/ *: */:/g' | grep -o 'id:[0-9]*'
    

    将返回:

    id:123
    id:5678
    id:567
    id:3643
    id:6721
    

    sed 命令用于删除与冒号相邻的所有空格,产生以下输出:

    id:123, name:test, id:5678, name john, address:new york
    id:567, name:bob
    id:3643, name:meg, id:6721, name kate, address:la
    

    并且grep -o 命令查找与id: 的所有匹配项,以零个或多个数字开头,-o 仅返回输入字符串的匹配部分。

    根据手册页:

    -o, --only-matching    Print only the matched (non-empty) parts of a matching 
                           line, with each such part on a separate output line.
    

    (仅供参考,grep 和 sed 命令正在使用正则表达式。)

    编辑: 对不起,我没有仔细阅读。我看到您反对-o 每行一个值的输出格式。回到绘图板...

    注意:如果您反对-o 输出的原因是为了保留行号,则使用grep -no 将给出以下输出(其中第一个数字是行号):

    1:id:123
    1:id:5678
    2:id:567
    3:id:3643
    3:id:6721
    

    也许这有帮助?

    【讨论】:

      【解决方案2】:

      这可能对你有用(GNU sed):

      sed -r 's/\<id:\s*/\n/g;s/,[^\n]*//g;s/\n/, id:/g;s/^, //' file
      

      将单词id: 和任何后续空格转换为唯一标记(在本例中为\n)。删除,\n 之后的任何内容。将\n 替换为标记, id:,然后删除前导,

      【讨论】:

      • 我尝试了几个小时来让它工作,但没有结果。我必须学习更多。 :)
      【解决方案3】:

      这应该可行:

       awk -F, '{id=0;for(i=1;i<=NF;i++) if($i~/id:/) id=id?id FS $i:$i; print id}' file
      

      测试:

      $ cat file
      id:123, name:test, id: 5678, name john, address:new york  
      id:567, name:bob  
      id:3643, name:meg, id: 6721, name kate, address:la  
      
      $ awk -F, '{id=0;for(i=1;i<=NF;i++) if($i~/id:/) id=id?id FS $i:$i; print id}' file
      id:123, id: 5678
      id:567
      id:3643, id: 6721
      

      【讨论】:

        【解决方案4】:
        perl -lne 'push @a,/id:[^,]*/g;print "@a";undef @a' your_file
        

        测试如下:

        > cat temp
        id:123, name:test, id: 5678, name john, address:new york  
        id:567, name:bob  
        id:3643, name:meg, id: 6721, name kate, address:la  
        > perl -lne 'push @a,/id:[^,]*/g;print "@a";undef @a' temp
        id:123 id: 5678
        id:567
        id:3643 id: 6721
        >
        

        【讨论】:

          【解决方案5】:

          这只是一个已经给出的答案的变体。我个人更喜欢文件中的脚本版本而不是命令行(更好的控制,可读性)

          id.txt

          id:1, name:test, id:2, name john, address:new york
          编号:3,姓名:鲍勃
          id:4, name:meg, id:5, name kate, 地址:la
          
          

          id.akw

          {
          i=0
          for(i=1;i<=NF;i++)
          { if($i~/id:/)
          id=id?id $i:$i;}
          print id
          id=""
          }
          

          调用:awk -f id.awk id.txt
          输出:

          编号:1,编号:2, 编号:3, 编号:4,编号:5,

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-27
            • 2014-12-10
            • 1970-01-01
            • 2023-03-09
            • 1970-01-01
            • 2012-10-13
            相关资源
            最近更新 更多