我对 UNIX 以及一般编码都很陌生,并且花了很长时间试图解决这个问题,但没有成功。我确信这是一个非常简单的解决方案,但如果有人可以帮助我指出正确的方向。
我有一个 Summary.txt 文件,其中包含以下格式的数据
Name criteria1 2 3 4 5 6 7 8 9 10
Sample12345 w x y z
Sample12345.avg l m n
Sample12345.stdn o p q
Sample98765 w2 x2 y2 z2
Sample98765.avg l2 m2 n2
Sample98765.stdn o2 p2 q2
等等等等
我想组合相同样本编号的三行,并且只保留名字:
Name criteria1 2 3 4 5 6 7 8 9 10
Sample12345 w x y z l m n o p q
Sample98765 w2 x2 y2 z2 l2 m2 n2 o2 p2 q2
等等等等
我尝试过使用 sed,例如(在首先制作包含所有 Sample12345.avg Sample12345.stdn 等的 Summary_temp.txt 之后):
for i in `cat Summary_temp.txt`; do sed 's/\n$i//g' Summary.txt; done
给出“-bash:意外标记'sed'附近的语法错误”
我也尝试过走这条路
paste -sd ' ' Summary.txt | sed 's/\t/\n/g10; s/\t/@/g; s/\n/\t/g' | sed 's/.\nSample.*.avg//g' | head
我相信我得到的最接近的是:
cat Summary.txt | sed 's/ *| */,/g;/^$/d' | paste -d, - - - | head
然而,这从第一行开始,所以所有内容都减一:
Name criteria1 2 3 4 5 6 7 8 9 10 Sample12345 w x y z Sample12345.avg l m n
Sample12345.stdn o p q Sample98765 w2 x2 y2 z2 Sample98765.avg l2 m2 n2
Sample98765.stdn o2 p2 q2 ETC ETC
我已经尝试过了
head -1 Summary.txt > Summary_temp_3.txt
,所以我可以稍后将其添加回来。
sed '1d' Summary.txt > Summary_temp_4.txt
cat Summary_temp_4.txt | sed 's/ *| */,/g;/^$/d' |
paste -d, - - - | sed 's/,.*_by_name//g | head
这根本没有显示出任何东西;我最终必须按 ctrl-C,所以假设它是错误的,因为它不应该花那么长时间。请帮忙。我知道我是一个初学者,这可能是一个很容易解决的愚蠢问题,但我不知道还能尝试什么。
答案1
它不是特别优雅,但是对于第二行到最后一行 ( 2,$
),将N
ext 行和N
ext 行拉入模式空间,然后g
全局替换换行符后面的任何非空白序列:
sed '
2,${
N
N
s/\n[^[:blank:]]*//g
}
' Summary.txt
Name criteria1 2 3 4 5 6 7 8 9 10
Sample12345 w x y z l m n o p q
Sample98765 w2 x2 y2 z2 l2 m2 n2 o2 p2 q2
答案2
+paste
方法sed
可能是(假设文件不包含,
字符):
$ paste -sd '\n,,' your-file | sed 's/,[^[:blank:]]*//g'
Name criteria1 2 3 4 5 6 7 8 9 10
Sample12345 w x y z l m n o p q
Sample98765 w2 x2 y2 z2 l2 m2 n2 o2 p2 q2
答案3
如果您的输入数据是一致的,即每三行共享组中第一行的第一个字段,那么您只需要一个awk
命令 - 如下所示:
awk '
NR==1{print;next}
NR%3==0{$1="";printf $0}
NR%3==1{$1="";printf $0;print ""}
NR%3==2{printf $0}
' infile
结果:
Name criteria1 2 3 4 5 6 7 8 9 10
Sample12345 w x y z l m n o p q
Sample98765 w2 x2 y2 z2 l2 m2 n2 o2 p2 q2
答案4
使用乐(以前称为 Perl_6)
您所描述的内容最好由散列,因为它们keys
保持独特。如果不存在这样的键值对,则附加键值对将作为新对添加到哈希中key
,否则values
将附加到预先存在key
的同名键值对中。举个简单的例子:
~$ raku -ne 'BEGIN my %h; %h.append: .split(" ", 2); END .put for %h.sort;' file
上面的代码处理一个简单的第一列“键”,该行的其余部分成为“值”。对于OP给出的更复杂的数据集,您需要消除.stdn
和.avg
扩展:
~$ raku -ne 'BEGIN my %h; \
.split(/ \. <alpha>+ | \s+ /, :skip-empty) andthen \
%h.append(.[0] => .[1..*]); \
END .put for %h.sort;' file
更全面地解释:Raku 代码是使用-ne
非自动打印逐行标志运行的。在循环各行之前,我们BEGIN
声明一个散列,%h
.然后,行split
位于\. <alpha>+
(例如“.avg”或“.stdn”)或\s+
空白上。分割后,我们重新加载$_
,andthen
然后append
使用键值对进行%h
哈希。 “粗箭头”语法=>
表示/创建一个键值对,如.[0] => .[1..*]
.第一列 (index = 0
) 成为key
,而其余 (index = 1..*
) 元素成为values
。
输入示例:
Name criteria1 2 3 4 5 6 7 8 9 10
Sample12345 w x y z
Sample12345.avg l m n
Sample12345.stdn o p q
Sample98765 w2 x2 y2 z2
Sample98765.avg l2 m2 n2
Sample98765.stdn o2 p2 q2
示例输出(键和值之间的 TAB):
Name criteria1 2 3 4 5 6 7 8 9 10
Sample12345 w x y z l m n o p q
Sample98765 w2 x2 y2 z2 l2 m2 n2 o2 p2 q2
最后,如果您想使用 CSV 文件的输出,您可以将join
所有元素放在逗号上(包括单个值)。完整答案如下:
~$ raku -ne 'BEGIN my %h; \
.split(/ \. <alpha>+ | \s+ /, :skip-empty) andthen \
%h.append(.[0] => .[1..*]); \
END put .keys ~ "," ~ .values.map: *.join(",") for %h.sort;' file
Sample98765,w2,x2,y2,z2,l2,m2,n2,o2,p2,q2
Sample12345,w,x,y,z,l,m,n,o,p,q
Name,criteria1,2,3,4,5,6,7,8,9,10
作为对代码的双重检查,更改:
.values.map: *.join(",")
到.values.map: *.elems
返回列数value
,每个键 10:
Name,10
Sample12345,10
Sample98765,10