有没有一种方法可以对列的一部分进行分组?

时间:2020-09-08 00:57:24

标签: shell awk sed

我有一个这样的TAB文件:

1   56  .   T   C   1963    .   HaplotypeScore=3.6230;MLEAF=1.00;MQ=60.00;MQ0=0;QD=33.84;MLEAC=1;SOR=1.077
1   226 .   A   G   1600    .   HaplotypeScore=3.0421;MLEAC=1;MLEAF=1.00;MQ=59.02;MQ0=0;QD=32.00;SOR=0.954
1   670 .   A   G   2878    .   HaplotypeScore=9.0166;QD=34.24;MLEAC=1;MLEAF=1.00;MQ=60.00;MQ0=0;SOR=0.864
1   817 .   C   T   1425    .   HaplotypeScore=0.9958;MLEAC=1;MLEAF=1.00;MQ=60.00;MQ0=0;QD=26.89;SOR=0.850

我的目标是创建一个for循环,从该列中单独提取QD=值并生成一个.txt文件,如下所示:

QD=33
QD=32
QD=34
QD=26

到目前为止,我已经提出了这样的建议:

awk -F'[:]''{print $ 8}'输入文件

,或者甚至使用sed命令。但是此刻我完全迷路了。

4 个答案:

答案 0 :(得分:3)

这里:

cut -d';' -f6 file

如果这是您所需要的,则不需要sedawk

仅进一步获取整数:

cut -d';' -f6 file|cut -d. -f1

编辑

更多评论表明QD=所在的列的顺序可能会发生变化,因此我们可以使用正则表达式来查找它:

grep -Po 'QD=\d+' file

示例:https://regex101.com/r/fCcDKe/1

答案 1 :(得分:3)

您的另一个选项是awk,它是文本处理的瑞士军刀。这将比在大文件上生成多个子shell并将管道信息传递给不同的实用程序快几个数量级。如果您少于1000条记录(行),则不会有太大差异。如果您有数百万行,则使用awk只需几分之一秒,而使用多个实用程序则只需几分钟。

awk处理文件中的每个记录(行),并按照写入顺序将写入规则应用于每个记录。有两个特殊规则,BEGIN(在读取行开始之前运行,可用于分配变量,打印标题行等)和END规则(在处理所有行之后运行)您可以处理数组中收集的任何数据或打印页脚行等。)

这里您需要一个规则,根据';'分隔符将最后一个字段分割成一个数组,例如

awk -F'\t' '{split($NF,arr,";"); sub(/[.].*$/,"",arr[6]); print arr[6]}' file

-F'\t'上方告诉awk使用制表符作为字段分隔符。 (注意:您可以省略-F'\t',因为awk会以空格分隔字段,然后,split将最后一个字段(NF)拆分为数组{{1 }},然后arr应用正则表达式sub来截取从/[.].*$/到字段末尾的所有内容,从而使问题中显示的整数消失,例如

使用/输出示例

将示例数据保存在名为'.'的文件中,您将具有:

file

(如果该字段发生了很多变化,您也可以遍历$ awk -F'\t' '{split($NF,arr,";"); sub(/[.].*$/,"",arr[6]); print arr[6]}' file QD=33 QD=32 QD=34 QD=26 的元素以找到以arr开头的元素)

未知量子点的位置

如果"QD"在最后一个字段中的位置未知,则可以简单地遍历"QD"的元素,例如arr并找到以for (i in arr)开头的元素,然后操作"QD"而不是arr[i],例如

arr[6]

您可以将名称从awk '{ split($NF,arr,";") for (i in arr) if (arr[i] ~ /^QD/) { sub(/[.].*$/,"",arr[i]) print arr[i] next } }' file 更改为您的文件名,然后选择复制并将鼠标中键将表达式粘贴到xterm中,并在其中包含您文件的当前工作目录,例如

使用/输出示例

file

或者,如果您更喜欢将其作为单线,则可以执行以下操作:

$ awk '{
>     split($NF,arr,";")
>     for (i in arr)
>         if (arr[i] ~ /^QD/) {
>             sub(/[.].*$/,"",arr[i])
>             print arr[i]
>             next
>         }
> }' file
QD=33
QD=32
QD=34
QD=26

GNU Awk Users Guide - String-Manipulation Functions中详细说明了所使用的所有功能。它是学习$ awk '{split($NF,arr,";"); for (i in arr) if (arr[i] ~ /^QD/) { sub(/[.].*$/,"",arr[i]); print arr[i]; next }}' file QD=33 QD=32 QD=34 QD=26 的绝佳参考。只需单击目录,然后将链接标记为完整指南。仔细研究一下,如果您还有其他问题,请告诉我。

答案 2 :(得分:3)

我认为最简单的方法应该是使用let jsonData = { "mood":[ { "id":"1", "text":"Annoyed", "cols":1, "rows":2, "color":"lightgreen", "route":"/angry", "musics":[ { "id":"0", "name":"English- Heaven's Peace", "image":"images/music.png", "link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EgleopO8DiEdsNKgqYZZSEKF", "descpription":"Tunes that soothe your pained soul", "reviews":[ { "name":"abc", "rating":4, "review":"energetic", "date":"" } ] }, { "id":"1", "name":"English- Hell's Fire", "image":"images/music.png", "link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EgmZitRQf1X1iYwWW_nUF44L", "descpription":"Beats that match the ones of your heart", "reviews":[ { "name":"abc", "rating":3.5, "review":"energetic", "date":"" } ] }, { "id":"2", "name":"Hindi", "image":"images/music.png", "link":"", "descpription":"", "reviews":[ { "name":"abc", "rating":4, "review":"energetic", "date":"" } ] }, { "id":"3", "name":"Punjabi", "image":"images/music.png", "link":"https://www.youtube.com/playlist?list=PLPfXrbtn3Egnntch2thUO55YqPQgo4Qh7", "descpription":"", "reviews":[ { "name":"abc", "rating":4, "review":"energetic", "date":"" } ] }, { "id":"4", "name":"Mix and Match", "image":"images/music.png", "link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EglN5LVTETqH3ipRLfXmY6MB", "descpription":"", "reviews":[ { "name":"abc", "rating":5, "review":"energetic", "date":"" } ] } ] } ] } ; // music - i can save here let r = jsonData.mood[0].musics.filter(data => data.id == "2"); // music - or i can console.log it also // i am comparing with 2 here - compare with your id number // according to your need console.log(jsonData.mood[0].musics.filter(data => data.id == "2")); // in the same way you can search mood also console.log(jsonData.mood.filter(data=> data.id == "1")); 的{​​{1}}函数,因为match的位置未知。在链接https://ideone.com/EzswQj#stdin

中进行了编写和测试
awk

说明: 使用此处的QD的{​​{1}}函数,我们可以在其中提供正则表达式以获取输出所需的内容。我给了awk 'match($NF,/QD=[0-9]+/){print substr($NF,RSTART,RLENGTH)}' Input_file ,它将匹配字符串QD then =,然后在最后一个字段中连续任意位数。在awk中,如果匹配一个正则表达式,它将设置两个名为matchQD=[0-9]+的默认变量,因此我在此处打印从RSTART到RLENGTH打印的子字符串。

注意: 根据显示的示例,考虑到QD值仅在最后一列出现一次,如果每行有多个值,那么我们需要写一会儿循环进入上面的代码。

答案 3 :(得分:1)

或者,一个简单的sed命令可以完成任务:

sed 's/.*;\(QD=[0-9]*\).*/\1/' file
相关问题