我有一个像这样的制表符分隔文件:
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列始终是单个值,而类似的问题有多个值,以col 1中的逗号分隔。我无法通过查看类似的问题找到我的解决方案。希望这个问题足够明显,可以留在这个网站上,并希望也能帮助其他人。
答案 0 :(得分: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 :(得分: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
中的所有元素,并根据(第一个字段,数组元素)对打印一行。
答案 2 :(得分: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
为输入设置auto-chomp,为输出设置auto-newline。 -F
开关隐式设置-a
(表示自动拆分为@F
)和-n
(这意味着迭代在命令行上传递的输入文件)。 / p>
-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
循环)来单独派生颜色。< / p>
描述脚本版本:
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运营商概述,包括<>
。此外,如果您的数据比显示的更复杂,使用诸如引用和转义分隔符之类的构造,您可能更愿意使用Text::CSV
CPAN模块来解析TSV / CSV文件。
答案 3 :(得分:0)
这可能适合你(GNU sed):
sed -r 's/^((\S+\s+)[^,]+),/\1\n\2/;P;D' file
将每个,
替换为换行符,后跟键及其空格(制表符)。
答案 4 :(得分:0)
关注awk也可以帮助你。
awk '{gsub(/,/,RS $1"&");gsub(/,/," ")} 1' Input_file
<强> 说明: 强>
gsub(/,/,RS $ 1“&amp;”): 使用awk的全局替换实用程序替换RS
行中的每个逗号(新行)$ 1(该行的第一个字段)“&amp;”这里用逗号表示(表示我们提到要替换的变量/正则表达式)。
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