Awk 拆分行的第二列以使用bash oneliner创建多行

Awk 拆分行的第二列以使用bash oneliner创建多行,awk,sed,cut,tr,Awk,Sed,Cut,Tr,我有一个选项卡分隔数据,它如下所示: a 1a,2x,c1 b2 a4,4.6 3c 323 sed -Ef parse.sed infile 第二列有多个逗号分隔的值。 我希望获得以下输出: a 1a a 2x a c1 b2 a4 b2 4.6 3c 323 我可以用我编写的python代码来实现这一点: import sys f = sys.argv[1] with open(f) as f: for line in f: line

我有一个选项卡分隔数据,它如下所示:

a   1a,2x,c1
b2  a4,4.6
3c  323
sed -Ef parse.sed infile
第二列有多个逗号分隔的值。 我希望获得以下输出:

a   1a
a   2x
a   c1
b2  a4
b2  4.6
3c  323
我可以用我编写的python代码来实现这一点:

import sys
f = sys.argv[1]

with open(f) as f:
    for line in f:
        line = line.strip("\n").split("\t")
        genes = line[1].split(",")
        for gene in genes:
            print(line[0],gene, sep="\t")
我知道我可以用bash脚本做同样的事情,但我想知道如何用一个很酷的bash oneliner,使用awk、sed、tr和/或cut,而不使用for循环来做这件事

我只能说:

tr',''\n'数据

$ awk -F$'\t' '{split($2,arr,","); for(e in arr) print($1, arr[e])}' file
a 1a
a 2x
a c1
b2 a4
b2 4.6
3c 323
如果希望选项卡位于第1列和第2列之间:

awk -F$'\t' '{split($2,arr,","); for(e in arr) print($1 "\t" arr[e])}'
a   1a
a   2x
a   c1
b2  a4
b2  4.6
3c  323
编辑:根据OP的要求,不使用循环(仅使用提供的样本进行测试和编写),(公平警告:
gsub
带有管道的版本是OP的好奇心,它比只使用for循环并将所有处理保持在
awk
内更脆弱、更慢):

简要说明:使用
awk
gsub
功能,用ORS(默认为新行it值)$1(根据OP要求的第一个字段)OFS(默认为空格its值)全局替换每行出现的
。然后提到
1
将在此处打印编辑/未编辑的行。然后将
awk
命令的输出传递到
column
命令,以相同的空间美化其输出

你能试试下面的吗

awk '{num=split($2,array,",");for(i=1;i<=num;i++){print $1,array[i]}}' Input_file
awk'{num=split($2,array,“,”);for(i=1;i
awk-F'[\t,]'''{for(i=2;已忽略)
sed-E:a;s/([^]+)*([^,]+),([^,]+)/\1\2\n\1\3/;ta'infle
解释 这是通过重复使用括号匹配3个组来实现的

  • ([^]+)
    匹配到第一个空格
  • ([^,]+)
    匹配到第一个逗号
  • ([^,]+)
    匹配可能的第二个逗号
  • \1\2\n\1\3
    将第一组匹配的内容替换为第二组,然后替换新行,再替换为第一组和第三组
便携式sed 解析

按如下方式运行:

a   1a,2x,c1
b2  a4,4.6
3c  323
sed -Ef parse.sed infile
两种情况下的输出:

a
2倍
c1
b2 a4
b2 4.6
3C323

为避免编写循环,GNU awk用于多字符RS:

$ awk -v RS='[,\n]' 'NF>1{k=$1} {print k, $NF}' file
a 1a
a 2x
a c1
b2 a4
b2 4.6
3c 323
相比之下,循环更清晰、更简单,并且可以与每个UNIX设备上任何shell中的任何awk一起工作:

$ awk -F'[[:space:]]+|,' '{for (i=2; i<=NF; i++) print $1, $i}' file
a 1a
a 2x
a c1
b2 a4
b2 4.6
3c 323
$awk-F'[:space:]+|,'{for(i=2;i这可能适合您(GNU-sed):


将前两个制表符分隔的值后跟逗号替换为前两个制表符分隔的值,换行符和第一个值后跟制表符。打印并删除图案空间中的第一行,然后重复。

不使用for循环是否可以执行此操作?不使用for循环是否可以执行此操作?是的,但为什么?您的Python脚本有一个
for
循环。为什么要使
awk
脚本更慢或更脆弱?请您解释一下代码,以便我能更好地理解它?当
$1
包含
&
时,第一个脚本将以静默和神秘的方式失败。第二个解决方案避免正则表达式,并解决存在
&
或任何其他问题
$1
中的regex元字符你能解释一下代码吗,这样我就能更好地理解它了?谢谢。现在这很有创意……而且不
for
循环使用for循环会更好吗?是的,因为它更清晰、更简单,并且可以在每个UNIX框上的任何shell中与任何awk一起工作。
awk-F'[:blank:],]+“…”
消除了交替。@anubhava是的,但如果有任何空字段,它就会失败,因为
将被视为一个单独的FS.idk,如果在这种情况下可以有空字段或没有空字段,当然,但我只是出于安全考虑。
$ awk -F'[[:space:]]+|,' '{for (i=2; i<=NF; i++) print $1, $i}' file
a 1a
a 2x
a c1
b2 a4
b2 4.6
3c 323
sed -E 's/^((.*\t)[^,]+),/\1\n\2/;P;D' file