从第二行开始将每 3 行组合在一起,并从组合的第二行和第三行中删除第一列

从第二行开始将每 3 行组合在一起,并从组合的第二行和第三行中删除第一列

我对 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,$),将Next 行和Next 行拉入模式空间,然后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

https://docs.raku.org/language/hashmap
https://raku.org

相关内容