在bash脚本中使用awk根据特定行中的字符数选择行范围

问题描述 投票:1回答:1

这似乎是在单个长awk命令中可能的事情。但我不知道awk做得好。

我想从第2行开始,在每第4行输入中识别ATGC字符的总数。如果任何行号是4的倍数,则字符数在1000到3000之间,然后我希望它打印该行以及上面的行和下面的两行。

我可以将其分解并在单独的代码行中执行部分操作。但是当我有数百万行时,计算时间太长。我需要一个强大的awk命令。在awk必须有一个足够聪明的人才能解决这个问题!

非常小的例子,范围10 < character count < 40: 输入:

@d0aec33d-ba    
TCAGTATGCTTCGTGCAATCAAG    
+    
-0(''$&"('    
@ee487ad3-b71    
ACAATGTG    
+    
""%#0&'+367<677

输出:

@d0aec33d-ba    
TCAGTATGCTTCGTGCAATCAAG    
+    
-0(''$&"('    
bash awk text-processing
1个回答
3
投票

这是一个快速的:

$ awk '
NR%4==1 { b="" }                                # first record of four, reset buffer
NR%4==2 && length()>10 && length()<40 { f=1 }   # 2/4 if length is right, flag up
{ b=b $0 ORS }                                  # buffer records to b
NR%4==0 && f {                                  # 4/4 
    printf "%s",b                               # print if flag is up
    f=0                                         # and flag down
}' file                 

输出:

@d0aec33d-ba
TCAGTATGCTTCGTGCAATCAAG
+
-0(''$&"('

编辑:

参数化版本(x=$miny=$max):

$ awk -v x=$min -v y=$max '
NR%4==1 { b="" }                                # first record of four, reset buffer
NR%4==2 && length()>x && length()<y { f=1 }     # 2/4 if length is right, flag up
{ b=b $0 ORS }                                  # buffer records to b
NR%4==0 && f {                                  # 4/4 
    printf "%s",b         #                     # print if flag is up
    f=0                 # #                     # and flag down
    # printf b; f=0   # # # # # # # # # # # # # # if commands on the same line                        
}' file                 # #
                          #

单行内容以防万一:

$ awk -v x=$min -v y=$max 'NR%4==1{b=""} NR%4==2 && length()>x && length()<y{f=1} {b=b $0 ORS} NR%4==0 && f{printf "%s",b; f=0}' file
© www.soinside.com 2019 - 2024. All rights reserved.