如何只显示匹配行之后的行?

如何只显示匹配行之后的行?

我有一个文件A.tsv(字段分隔符 = \t):

for Research Use Only                       
                        
[Header]                        
Test Name   Il          
Run ID  2102                
Run Date    2021-02-04                  
Report Date/Time    2021-02-05 08:48                    
Instrument Serial                       
Flow Cell ID                    
Software Version                    
                        
[Quality Control]                       
Lane 1,2,3,4    PASS                    
Lane 1,2,3,4 Index Set 1    PASS                    
                        
[Patient Sample Results]                        
Sample ID   Internal Control    Result  Consensus Sequence  Lane    Index Set   Index ID
207 Pass        Not Available   1,2,3,4 1   UDP0001
205 Pass        Not Available   1,2,3,4 1   UDP0002

[Control Sample Results]                        
Sample ID   Control Type    Human Control   SARS-CoV-2  Lane    Index Set   Index ID
CONTROL-POS Positive Control    Not Detected    Detected    1,2,3,4 1   UDP0008

我只想在新文件中打印这些行:

Sample ID   Internal Control    Result  Consensus Sequence  Lane    Index Set   Index ID
207 Pass        Not Available   1,2,3,4 1   UDP0001
205 Pass        Not Available   1,2,3,4 1   UDP0002
CONTROL-POS Positive Control    Not Detected    Detected    1,2,3,4 1   UDP0008

所以我想打印[Patient Sample Results]and之后的行[Control Sample Results],但只打印标题行一次。

该文件是子采样,不能使用行号对其进行硬编码。

所以我尝试了类似的东西:

awk '/Patient Sample Results/{getline; print}' A.tsv > data_info.tsv

但它只打印第一个模式之后的行。你有办法解决我的问题吗?

答案1

假设您的[ ... ]部分由空行分隔(其中不得包含空格/制表符),并且您想要打印以 开头的所有部分的内容[Patient Sample Results],以下应该可以工作:

awk -F"\n" -v RS="" '$1~/^\[Patient Sample Results\]/{s=2}
                     s{for (i=s;i<=NF;i++) print $i; s=3}' A.tsv > data_info.tsv

这将指示awk在“段落模式”下操作,将任何空行组视为记录分隔符,将换行符视为字段分隔符。

  • “章节标题”现在将显示为$1记录的第一个“字段”( )。

  • 一旦第一个字段(=行)或记录以 开头[Patient Sample Results],我们设置一个标志s2指示

    1. 我们想要从现在开始打印结果,并且
    2. 我们想要(最初)打印从第二行(=字段)开始因为第一次我们要打印“标题”行。

    注意我使用正则表达式比较$1 ~而不是完整字符串比较$1==来防止可能的尾随空格/制表符。

  • 如果s设置,则打印以 number 开头的字段(=行)s,该字段最初为 2。然后,将其设置为 3,以便我们将来跳过“标题”行。

由于字段(=行)“按原样”打印,因此这将保留输入文件中找到的分隔符。

如果您的部分由实际包含空格的“空”行分隔,以下修改需要 GNUawk进行多字符记录分隔符,将防止这种情况发生(请参阅@EdMorton 在 StackOverflow 上的回答例如):

awk -F'\n' -v RS='\n(([[:space:]]*\n)+|$)' ' ... '

这会将任意数量的“完全空或仅包含空白字符的行”作为记录分隔符。

答案2

也许像

awk 'BEGIN {FS="\t"}
     /^\[Patient Sample Results]/ { printing=1 ; next }
     !printing { next }
     /^\[/ { next }
     /^[ \t]*$/ { next }
     /^Sample/ { if (!printedheader) { print }; printedheader=1 ; next }
     { print }'
  1. 设置字段分隔符为tab,实际不需要
  2. 请注意我们何时必须开始打印
  3. 如果我们尚未打印,则跳到下一行
  4. 不要打印以以下内容开头的行[
  5. 跳过空白行,仅定义为空格和制表符。
  6. 如果这是标题,请在第一次看到它时打印它,然后跳到下一行。
  7. 打印剩余的内容

写得尽可能明显,而不是使用 awk 习惯用法,例如1代替{ print }.

编辑。更改空行的定义以响应评论。

答案3

尝试:

awk '/\[(Patient|Control) Sample Results\]/{ hdr++; next }
     hdr==2        { hdr--; next }
     hdr && !rep   { print; rep=1; next }
     rep && $0!="" { print }
' infile

答案4

使用GNU sed我们可以执行以下操作,无论配置文件 A.tsv 中列出的是患者还是对照样本结果,顺序都无关紧要

sed -En '
  /\[(Patient|Control) Sample Results]/,/^\s*$/{
    //!{p;d;}
    /\S/!d;n;G
    /\n./n;P;h
  }
' A.tsv

一些术语:在一系列行中,/begin/,/end/第一个和最后一个是该范围的边界框,可以通过//正则表达式访问。同样,内部也可通过 访问//!。前提是这是我们在输入范围时使用的第一个正则表达式。

相关内容