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;iawk-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