首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在单独的字段中在字符串匹配之间打印n行数

在单独的字段中在字符串匹配之间打印n行数
EN

Stack Overflow用户
提问于 2019-12-05 15:04:53
回答 3查看 55关注 0票数 0

我有两个文件,File_1包含I,File_2包含要匹配的数据。每个文件如下所示:

代码语言:javascript
复制
File_1
Cluster 43
Cluster 51
Cluster 145
Cluster 160

File_2
>Cluster 43
0       5249nt, >CL276.Contig2_All... at +/98.55%
1       6413nt, >CL276.Contig3_All... *
2       5375nt, >CL276.Contig5_All... at +/95.91%
3       5405nt, >CL276.Contig6_All... at +/98.33%
>Cluster 51
0       6298nt, >CL5173.Contig2_All... *
1       3421nt, >CL5173.Contig3_All... at +/99.50%
2       1017nt, >CL5173.Contig4_All... at +/98.13%
3       503nt, >Unigene10077_All... at +/98.01%
>Cluster 145
0       4772nt, >CL1798.Contig5_All... at +/98.49%
1       4782nt, >CL1798.Contig8_All... *
2       4781nt, >CL1798.Contig10_All... at +/99.27%
3       4773nt, >CL1798.Contig11_All... at +/99.25%
>Cluster 160
0       2883nt, >CL4790.Contig2_All... at +/95.87%
1       4699nt, >CL4790.Contig3_All... *
2       1274nt, >CL4790.Contig7_All... at +/99.37%
3       4616nt, >CL4790.Contig14_All... at -/95.65%

我需要在File_2中找到与File_1中的in匹配的所有行,并打印匹配的行(如“集群43”),并在单独的字段中打印匹配字符串之间的所有行。所需的输出应该如下所示

代码语言:javascript
复制
Cluster 43 5249nt CL276.Contig2_All
           6413nt CL276.Contig3_All
           5375nt CL276.Contig5_All
           5405nt CL276.Contig6_All
Cluster 51 6298nt CL5173.Contig2_All
           3421nt CL5173.Contig3_All
           1017nt CL5173.Contig4_All
           503nt Unigene10077_All

使用我的逗号行(见下文),我可以处理文件,根据来自File_2的ID在File_1中获得匹配的行,打印匹配的行和匹配之间的所有行,并从每一行中删除所有不想要的信息,但是,我在找到一个解决方案来在一个单独的字段中打印匹配的匹配行时遇到了问题,如上面所示的期望输出中所示。

我的命令行

代码语言:javascript
复制
$ grep -A4 -Fwf File_1 File_2 | sed 's/All.*//g;/Contig/s/.$/_All/g;/Unigene/s/.$/_All/g;s/-.*//;/^$/d;s/.//;s/[,>]//g' | awk '{print $1, $2}' > my_wanted_file

结果输出

代码语言:javascript
复制
$head my_wanted_file

Cluster 43
5249nt CL276.Contig2_All
6413nt CL276.Contig3_All
5375nt CL276.Contig5_All
5405nt CL276.Contig6_All
Cluster 51
6298nt CL5173.Contig2_All
3421nt CL5173.Contig3_All
1017nt CL5173.Contig4_All
503nt Unigene10077_All

为了实现我的目标,我编写了以下命令行:

代码语言:javascript
复制
$ awk '/^Cluster/ {if ('\n') {printf NR==4}}' my_wanted_file | head

但它什么也没印。

然后我试着:

代码语言:javascript
复制
$ awk '/Cluster/ {for(i=1; i<=4; i++) {getline; print}}' my_wanted_file | head

但是它只连续地打印每个匹配(集群)之间的行,如下所示

代码语言:javascript
复制
5249nt CL276.Contig2_All
6413nt CL276.Contig3_All
5375nt CL276.Contig5_All
5405nt CL276.Contig6_All
6298nt CL5173.Contig2_All
3421nt CL5173.Contig3_All
1017nt CL5173.Contig4_All
503nt Unigene10077_All
4772nt CL1798.Contig5_All
4782nt CL1798.Contig8_All

我找不到路要走

代码语言:javascript
复制
Cluster 43
5249nt CL276.Contig2_All
6413nt CL276.Contig3_All
5375nt CL276.Contig5_All
5405nt CL276.Contig6_All
Cluster 51
6298nt CL5173.Contig2_All
3421nt CL5173.Contig3_All
1017nt CL5173.Contig4_All
503nt Unigene10077_All

到这个

代码语言:javascript
复制
Cluster 43 5249nt CL276.Contig2_All
           6413nt CL276.Contig3_All
           5375nt CL276.Contig5_All
           5405nt CL276.Contig6_All
Cluster 51 6298nt CL5173.Contig2_All
           3421nt CL5173.Contig3_All
           1017nt CL5173.Contig4_All
           503nt Unigene10077_All

我非常感谢在这方面提供一点帮助。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-05 15:54:02

你能试一下吗。虽然我不确定您是否需要值直到All或字符串at之前,或者All是否真的出现在您的Input_file中,因此我们也可以相应地更改正则表达式。

这也将为所有行提供相等的空间。

代码语言:javascript
复制
awk '
FNR==NR{
  $0=">"$0
  a[$0]
  max=max>length($0)?max:length($0)
  next
}
FNR==1 && FNR!=NR{
  spaces=sprintf("%-"max+1"s",OFS)
}
/^>/{
  found=val=count=""
}
/^>/ && $0 in a{
  found=1
  val= $0
  remain_spaces=sprintf("%-"max-length($0)+1"s",OFS)
  next
}
found{
  gsub(/^>|at.*/,"",$3)
  sub(/,/,"",$2)
  printf("%s\n",++count==1?val remain_spaces $2 OFS $3:spaces $2 OFS $3)
}
'  Input_file1  Input_file2

输出如下。

代码语言:javascript
复制
>Cluster 43  5249nt CL276.Contig2_All...
             6413nt CL276.Contig3_All...
             5375nt CL276.Contig5_All...
             5405nt CL276.Contig6_All...
>Cluster 51  6298nt CL5173.Contig2_All...
             3421nt CL5173.Contig3_All...
             1017nt CL5173.Contig4_All...
             503nt Unigene10077_All...
>Cluster 145 4772nt CL1798.Contig5_All...
             4782nt CL1798.Contig8_All...
             4781nt CL1798.Contig10_All...
             4773nt CL1798.Contig11_All...
>Cluster 160 2883nt CL4790.Contig2_All...
             4699nt CL4790.Contig3_All...
             1274nt CL4790.Contig7_All...
             4616nt CL4790.Contig14_All...
票数 1
EN

Stack Overflow用户

发布于 2019-12-05 16:28:00

这就是你想要做的(使用GNU awk来表示多个字符的RS、ENDFILE和\s ( [[:space:]]) )吗?

代码语言:javascript
复制
$ cat tst.awk
NR==FNR {
    tgts[$0]
    next
}
ENDFILE {
    RS = "(^|\n)(>|$)"
    FS = "\n"
}
(FNR > 1) && ($1 in tgts) {
    gsub(/\n[0-9]+\s+/,"\n")
    gsub(/[,>]|[.]{3}[^\n]*/,"")
    for (i=2; i<=NF; i++) {
        print $1, $i
        gsub(/./," ",$1)
    }
}

代码语言:javascript
复制
$ awk -f tst.awk File_1 File_2
Cluster 43 5249nt CL276.Contig2_All
           6413nt CL276.Contig3_All
           5375nt CL276.Contig5_All
           5405nt CL276.Contig6_All
Cluster 51 6298nt CL5173.Contig2_All
           3421nt CL5173.Contig3_All
           1017nt CL5173.Contig4_All
           503nt Unigene10077_All
Cluster 145 4772nt CL1798.Contig5_All
            4782nt CL1798.Contig8_All
            4781nt CL1798.Contig10_All
            4773nt CL1798.Contig11_All
Cluster 160 2883nt CL4790.Contig2_All
            4699nt CL4790.Contig3_All
            1274nt CL4790.Contig7_All
            4616nt CL4790.Contig14_All
票数 2
EN

Stack Overflow用户

发布于 2019-12-05 16:29:46

假设输入是:

代码语言:javascript
复制
Cluster 43
5249nt CL276.Contig2_All
6413nt CL276.Contig3_All
5375nt CL276.Contig5_All
5405nt CL276.Contig6_All
Cluster 51
6298nt CL5173.Contig2_All
3421nt CL5173.Contig3_All
1017nt CL5173.Contig4_All
503nt Unigene10077_All

假设每个集群都有5行代码,则可以执行以下操作:

代码语言:javascript
复制
sed 'N;s/[[:blank:]]*\n[[:blank:]]*/|/; n;s/^/|/; n;s/^/|/; n;s/^/|/'

或者像这样,看起来更短,不知道是不是更好:

代码语言:javascript
复制
sed 's/^/|/' | sed 's/^|//;N;s/\n//;N;N;N'

得到:

代码语言:javascript
复制
Cluster 43|5249nt CL276.Contig2_All
|6413nt CL276.Contig3_All
|5375nt CL276.Contig5_All
|5405nt CL276.Contig6_All
Cluster 51|6298nt CL5173.Contig2_All
|3421nt CL5173.Contig3_All
|1017nt CL5173.Contig4_All
|503nt Unigene10077_All

您可以选择其他分隔符,然后选择|。现在您可以通过column运行它来对其进行列列:

代码语言:javascript
复制
column -t -s '|' -o ' '

将产生以下结果:

代码语言:javascript
复制
Cluster 43 5249nt CL276.Contig2_All
           6413nt CL276.Contig3_All
           5375nt CL276.Contig5_All
           5405nt CL276.Contig6_All
Cluster 51 6298nt CL5173.Contig2_All
           3421nt CL5173.Contig3_All
           1017nt CL5173.Contig4_All
           503nt Unigene10077_All

我测试它的整个命令如下所示:

代码语言:javascript
复制
cat <<EOF |
Cluster 43
5249nt CL276.Contig2_All
6413nt CL276.Contig3_All
5375nt CL276.Contig5_All
5405nt CL276.Contig6_All
Cluster 51
6298nt CL5173.Contig2_All
3421nt CL5173.Contig3_All
1017nt CL5173.Contig4_All
503nt Unigene10077_All
EOF
sed 'N;s/[[:blank:]]*\n[[:blank:]]*/|/; n;s/^/|/; n;s/^/|/; n;s/^/|/' | column -t -s '|' -o ' '
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59197966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档