【问题标题】:Using awk in a bash script to select line range based on number of characters in specific line在 bash 脚本中使用 awk 根据特定行中的字符数选择行范围
【发布时间】:2019-02-28 18:52:02
【问题描述】:

这似乎可以在单个长 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(''$&"('    

【问题讨论】:

  • 第4行可以有ATGC以外的字符吗?
  • 我不知道您的要求是什么意思,我无法想象对它们的任何解释如何从您发布的示例输入中产生您发布的预期输出。如果其他人运气更好,但您可能想澄清您正在尝试做的事情并解释为什么这是预期的输出。

标签: bash awk text-processing


【解决方案1】:

这是一个快速的:

$ 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

【讨论】:

  • 哇,真快,我还没有在更大的数据集上测试过它,但是我看不出它在哪里考虑了
  • 已修复。使用瀑布模型:D
  • 最后一块(你的评论中的{printf b f==0})是错误的。如果命令在同一行,它应该有一个分号和一个= 而不是==,即:{printf b; f==0}
  • 可能是printf b。用printf "%s",b 替换它应该可以解决这个问题。
  • 工作就像一个魅力,伟大的修复,漂亮的代码詹姆斯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多