我不确定我是否可以使用sed完全执行此操作:
我正在尝试重新排列这样的行
GF:001,GF:00012,GF:01223<TAB>XXR
GF:001,GF:00012,GF:01223,GF:0666<TAB>XXXR3
到
GF:001<TAB>XXR
GF:00012<TAB>XXR
GF:01223<TAB>XXR
GF:001<TAB>XXXR3
GF:00012<TAB>XXXR3
GF:01223<TAB>XXXR3
GF:0666<TAB>XXXR3
有人提示吗? GF:XXXX的基数交替为GF:XXXX的长度。
我被sed -n '
'/\(XX.*\)$/' {
s/,/\t\1\n/
}' input
困住了,但我不能首先引用最初匹配的模式。有任何想法吗?干杯!
更新: 我认为只使用sed就不可能做到这一点。所以我使用perl来做到这一点:
perl -e 'open(IN, "< file");
while (<IN>) {
@a = split(/\t/);
@gos = split(/,/, $a[0]);
foreach (@gos) {
print $_."\t".$a[1];
}
close( IN );' > output
但如果有人知道如何使用sed
解决此问题,请在此处发布...
答案 0 :(得分:7)
可以在sed
中完成,但我可能会使用Perl(或Awk或Python)来完成它。
我声称这种解决方案没有优雅,但蛮力和无知有时会得到回报。我创建了一个名为sed.script
的名为
/\(GF:[0-9]*\),\(.*\)<TAB>\(.*\)/{
:redo
s/\(GF:[0-9]*\),\(.*\)<TAB>\(.*\)/\1<TAB>\3@@@@@\2<TAB>\3/
h
s/@@@@@.*//
p
x
s/.*@@@@@//
t redo
d
}
我把它当作:
sed -f sed.script input
其中input
包含问题中显示的两行。它产生了输出:
GF:001<TAB>XXR
GF:00012<TAB>XXR
GF:01223<TAB>XXR
GF:001<TAB>XXXR3
GF:00012<TAB>XXXR3
GF:01223<TAB>XXXR3
GF:0666<TAB>XXXR3
(我冒昧故意将<TAB>
误解为5个字符的序列而不是单个制表符;您可以轻松修复答案以处理实际的制表符。)
sed
脚本的说明:
GF:nnn
出现的行(我们不需要处理包含单个此类事件的行)。只在这样的行上执行脚本的其余部分。其他任何东西都通过(打印)不变。<TAB>
之后的字段。将其替换为第一个字段<TAB>
,第三个字段,难以置信的标记模式(@@@@@
),第二个字段,<TAB>
,第三个字段。redo
标签。这是一个简单的循环,可以在每次迭代时将模式数量减少一个。
答案 1 :(得分:3)
你可以用awk直接做到:
$ awk '{gsub(/,/, "\t" $NF "\n");print}' input
在这种情况下,我们只需用与最后一个字段连接的标签替换逗号(NF
存储记录的字段数; $NF
获取NF
字段)与换行符连接。然后,打印结果。
它也可以用sed来解决,类似但恕我直言比Jonathan解决方案更好(这是非常复杂的,我应该说)。
sed -n '
:BEGIN
h
s/,.*<TAB>/<TAB>/
p
x
s/^[^,]*,//
t BEGIN' input
在这里,我们在脚本的开头定义一个标签:
:BEGIN
然后我们将模式空间的内容复制到保留空间:
h
现在,我们将第一个逗号中的所有内容替换为仅包含选项卡的选项卡:
s/,.*<TAB>/<TAB>/
我们打印结果......
p
...并检索保留空间的内容:
x
由于我们打印了第一行 - 其中包含第一个GF:XXX
模式,后跟最终XXR
模式 - 我们从该行中删除了第一个GF:XXX
模式:
s/^[^,]*,//
如果执行替换,我们将分支到脚本的开头:
t BEGIN
并且所有内容再次应用于同一行,但现在此行不再具有第一个GF:XXX
模式。 OTOH,如果没有替换,则完成当前行的处理,我们不再跳到开头。
答案 2 :(得分:2)
如果你不严格要求sed,awk擅长这样做:
awk -F'\t|,' '{ i=1; do { printf("%s\t%s\n",$i,$NF); i++;} while ( i<NF ); }' inputfile
答案 3 :(得分:2)
我花了3个小时才做到这一点
sed -re ':a; s/(GF:[0-9]*[^,]*),([^<]*)(<TAB>[A-Z]*)/\1\3\n\2\3/g;ta; ' file.txt
答案 4 :(得分:1)
awk -F'[,\t]' '{for (i=1;i<NF;i++) print $i"\t"$NF}' file
Awk一次读取一行(默认情况下)并将该行拆分为字段。我使用-F告诉awk将行分隔成每个逗号或制表符的字段。 NF是行中字段的数量,$ i是字段编号i的内容。