如何从每行出现一次或多次的文件中提取文本?

时间:2013-07-19 03:34:58

标签: unix sed awk grep

我有一个文本文件,每行有一个或多个电子邮件ID。 E.g。

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:值可能会在一行中出现一次或多次。如何提取所有id:值对,以便输出为

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

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

sed/awk应该做的但我是菜鸟

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

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

5 个答案:

答案 0 :(得分:2)

如果您的内容位于文件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

也许这有帮助?

答案 1 :(得分:2)

这可能适合你(GNU sed):

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

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

答案 2 :(得分:1)

这应该有效:

 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

答案 3 :(得分:0)

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
>

答案 4 :(得分:0)

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

id.txt

id:1, name:test, id:2, name john, address:new york  
id:3, name:bob  
id:4, name:meg, id:5, name kate, address: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
输出:

id:1, id:2,
id:3,
id:4, id:5,