2017-10-09 45 views
-1

第1列的值我有一个这样的制表符分隔文件:独立的第2列分隔列表,将新行,继承每新行

ID1 blue 
ID2 yellow,blue 
ID3 green,yellow,red 
ID4 red 
1D5 red,purple 

第二列,我需要分离出逗号列表,每个颜色在它自己的行上,并且对于每一个新行,我需要保留ID#。

我正在考虑使用sed来替换每个逗号用一个新行,但不知道如何添加关联的ID返回。 Awk或perl?一番搜索后,我找不到答案...

最终结果将没有逗号,看起来像这样:

最终结果:

ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 

任何帮助,非常感谢。 此问题与Bash turning single comma-separated column into multi-line string非常相似,但我的第1列总是单个值,而类似的问题有多个值,第1列用逗号分隔。我无法通过查看类似问题找到我的解决方案。希望这个问题足以让人留在这个网站上,并希望能够帮助其他人。

回答

1
$ awk -F'[\t,]' '{for (i=2;i<=NF;i++) print $1, $i}' file 
ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 
+1

非常感谢,埃德! – Cath

0

这个简单awk程序应该这样做:

$ awk -F'\t' '{ n=split($2,arr,","); for(i=1;i<=n;i++) print $1,arr[i] }' file 
ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 

我们分割线到字段上标签(\t),然后对每一行的逗号(,)与split()分裂的第二个字段。最后,我们遍历数组arr中的所有元素,并按照(第一个字段,数组元素)对打印一行。

0

你的问题被标记了各种实用程序/胶水语言,包括Perl,所以这个答案描述了使用Perl编程语言的解决方案。

这里是一个Perl单行溶液:

perl -lF/\\t/ -e 'print "$F[0] $_" for split /,/, $F[1]' test.txt 

鉴于制表符分隔的文件如本产生以下输出的问题描述:

ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 

这工作大致与以下内容相同完整Perl脚本:

while (<>) { 
    chomp; 
    next unless length; 
    my ($id, $colors) = split /\t/, $_; 
    print "$id $_\n" foreach split /,/, $colors; 
} 

在这些解决方案中,我使用\t在选项卡上分割,尽管您提供的示例数据似乎不是以空格分隔的,而是专门用于制表符分隔。如果您的数据实际上只是“空白”分隔符,请将\t更改为\s+

下面是一行代码是如何工作的:

-l台自动格格输入和自动换行输出。 -F切换隐式设置-a(意思是自动分割为@F)和-n(这意味着迭代在命令行上传递的输入文件)。

-F/\\t/表示在/\t/正则表达式上自动分割,换句话说,在制表符上填充@F并结果。 (如果您的数据更普遍空格分隔你可以改变\\t\\s+

因此,对于输入的每一行,$F[0]将包含IDx领域,$F[1]将包含颜色,如yellow,blue

-e命令行开关意味着评估以下代码,并且因为我们有-n隐含在-F中,所以我们迭代该文件并在输入文件的每行执行一次代码。

而我们在通过代码是:

print "$F[0] $_" foreach split /,/, $F[1] 

这意味着每文件的行,在颜色列表中的每个项,打印随后颜色的ID(存储在$F[0])(存储在$_)。

我们通过拆分$F[1],其中可能包含yellow,blue上逗号,并为每种颜色(使用foreach环)填充$_单独导出的颜色。

描述脚本版本:

while(<>) {...}读取在通过命令行(或从STDIN)上设置的文件一次一行,并且对于每个线填充$_

相关文章:

的Perl附带perldoc命令,可以用一块Perl的文档阅读的名字被调用的每一个完整的安装。

请参阅以下内容:

  • perldoc perlrun - Perl的命令行开关的说明。
  • perldoc perlintro - Perl简介。
  • perldoc perlre - 深入的Perl正则表达式概述。
  • perldoc -f split - 解释Perl的split函数的工作原理。
  • perldoc perlsyn - 描述Perl的控制结构,如foreach循环。
  • perldoc perlop - Perl操作员的概述,包括<>

此外,如果你的数据是复杂得多所示,使用结构,如报价和分隔符的逃避,你应该更喜欢解析TSV/CSV文件中Text::CSV CPAN模块。

+0

感谢您对所有的细节,戴维! – Cath

0

这可能为你工作(GNU SED):

sed -r 's/^((\S+\s+)[^,]+),/\1\n\2/;P;D' file 

一个换行符其次密钥及其空白(标签)替换每个,

0

以下awk也可能帮助你。

awk '{gsub(/,/,RS $1"&");gsub(/,/," ")} 1' Input_file 

说明:

GSUB(/,/,RS $ 1" &“):使用awk的全球替代工具来替代在一条线上每个逗号与RS(新行)$ 1(该行的第一个字段)“&”表示逗号在这里(表示我们提到要替换的变量/正则表达式)。

GSUB(/,/,”“):再次使用全球替代工具来awk,所以上述gsub会让INPUT_FILE看起来如下。

ID1 blue 
ID2 yellow 
ID2,blue 
ID3 green 
ID3,yellow 
ID3,red 
ID4 red 
1D5 red 
1D5,purple 

这不是我们OP的输出,所以再次全局地用简单的空格替换逗号,所以得到正确的输出如下。

ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 
+1

谢谢你,Ravinder! – Cath

+0

@Cath,欢迎你,很高兴它帮助你。看到这个https://stackoverflow.com/help/someone-answers享受学习和分享知识,欢呼:) – RavinderSingh13

相关问题