通过awk或grep处理文件

通过awk或grep处理文件,awk,grep,Awk,Grep,我必须处理一个大的输入文件(2.9 GB),以生成特定格式的输出(如下所述:) 输入文件的示例为: GS RSPH14 CC Build HSA_Jul2014 (GRCh38; hg38): chr22:23141092..23152092 (REVERSE) FT TFBS CHIP: FR000000873; SP1 (Jurkat); PMID:14980218; 23144712..23145380 FT TFBS CHIP: FR000643682; ER-ALPHA (MC

我必须处理一个大的输入文件(2.9 GB),以生成特定格式的输出(如下所述:)

输入文件的示例为:

GS  RSPH14
CC  Build HSA_Jul2014 (GRCh38; hg38): chr22:23141092..23152092 (REVERSE)
FT  TFBS CHIP: FR000000873; SP1 (Jurkat); PMID:14980218; 23144712..23145380
FT  TFBS CHIP: FR000643682; ER-ALPHA (MCF-7); PMID:19339991; 23147445..23148194
FT  TFBS CHIP: FR029934262; C/EBPBETA (A-549); https://www.encodeproject.org/experiments/ENCSR000DYI/; 23150853..23151108
GS  CLXC15
CC  Build HSA_Jul2014 (GRCh38; hg38): chr3:23144021..23155021 (REVERSE)
FT  TFBS CHIP: FR000643682; ER-ALPHA (MCF-7); PMID:19339991; 23147445..23148194
FT  TFBS CHIP: FR034213319; CTCF (MCF-7); https://www.encodeproject.org/experiments/ENCSR000DMV/; 23151393..23151582
说明:输入文件中的每一行都以
GS
CC
FT
开头,我想忽略GS*行。对于CC*行,我想在
上拆分它,并获取
第一个索引(基于0的计数),根据我的输入样本,它将是
chr22
(在第2行)和
chr3
(在第7行)。对于FT行,我想在
上拆分它
并获取
第一个
最后一个索引
(根据我的输入示例的第3行,它将分别是
SP1(Jurkat)
23144712..23145380
),并希望以这样的方式处理它们,使我的输出文件如下所示:

chr22   23144712    23145380    SP1
chr22   23147445    23148194    ER-ALPHA
chr22   23150853    23151108    C/EBPBETA
chr3    23147445    23148194    ER-ALPHA
chr3    23151393    23151582    CTCF
任何帮助都将不胜感激

我的尝试:我可以在
上拆分文件以便获得所需的列。我尝试的是:
awk-F'[;]'{print$2'\t'$4}'sample.txt>output.txt
。这使我的输出为:

 hg38): chr22:23141092..23152092 (REVERSE)  
 SP1 (Jurkat)    23144712..23145380
 ER-ALPHA (MCF-7)    23147445..23148194
 C/EBPBETA (A-549)   23150853..23151108

 hg38): chr3:23144021..23155021 (REVERSE)   
 ER-ALPHA (MCF-7)    23147445..23148194
 CTCF (MCF-7)    23151393..23151582
现在,从第1行和第6行开始,我只需要
chr22
chr3
,从其他行开始(非第1行和第6行,最初以
GS
CC
开头),只需要最后一列,并在前面附加相应的chr。另外,应处理其他行的第一个索引,以便在
上拆分(
并保留第一个索引。

使用awk:

awk '
    $1 == "CC" { split($0, a, /:/); key=a[2] }
    $1 == "FT" {
        n = split($0, a, /;/)
        split(a[2], b, FS)
        split(a[n], c, /[.]{2}/)
        print key, c[1],c[2], b[1]
    }
' file | column -t

下面的
awk
可能会对您有所帮助

awk '/^CC.*/{match($0,/chr[0-9]+/);val=substr($0,RSTART,RLENGTH);next} /^FT.*/{sub(/\.+/,OFS,$NF);print val,$NF,$5}' OFS="\t"  Input_file
现在也添加了一个非线性的解决方案

awk '
/^CC.*/{
  match($0,/chr[0-9]+/);
  val=substr($0,RSTART,RLENGTH);
  next}
/^FT.*/{
  sub(/\.+/,OFS,$NF);
  print val,$NF,$5}
' OFS="\t"  Input_file

根据您的要求;使用awk

$ awk '/^CC /{FS=":"; $0=$0; a=$2} /^FT /{FS="[ ;.]+"; $0=$0;print a,$(NF-1),$NF,$5}' file
 chr22 23144712 23145380 SP1
 chr22 23147445 23148194 ER-ALPHA
 chr22 23150853 23151108 C/EBPBETA
 chr3 23147445 23148194 ER-ALPHA
 chr3 23151393 23151582 CTCF
/^CC/{FS=“:”;$0=$0;a=$2;}
:如果记录以
CC
开头(注意空格),则将
设置为FS。
$0=$0
将强制awk根据
FS
是什么来分割记录。将
a
设置为第二个字段

/^FT/{FS=“[;。]+”;$0=$0;打印一个,$(NF-1),$NF,$5}
:如果记录以
FT
开头(再次注意空格),请将
[;]+
设置为
FS
,这将等同于重复的
例如

最后,打印所需的字段。

堆栈溢出不是免费的编码服务。您尝试了什么,它是如何失败的?这是我达到的程度:
awk-F'[;]'{print$2'\t'$4}'sample.txt>output.txt
,但我无法按照我的要求进一步拆分这些索引!请您的问题解释这些内容,最好是更详细一些(您到底被困在哪里?)@tripleee你现在能帮我吗?非常感谢你抽出时间回答。它工作得非常好。如果你能在代码行中添加简短的注释,这样我就可以更好地理解解决方案,并在将来根据我的需要修改它。我不明白
FS
split(a[2],b,FS)中做了什么
请解释这一行的拆分(a[n],c,/[.]{2}/)
谢谢!
FS
是常规的字段分隔符;因此该行首先拆分为分号,然后其中一个字段依次拆分为空格。
[.]{2}
匹配两个相邻的文字点。在这种情况下,FS的内容已经是split的默认分隔符,因此这也会起作用:
split(a[2],b)
GNU awk手册和
split()
函数非常感谢您抽出时间回答。我选择了另一个答案,因为它是第一个发布的,我尝试了,它首先起作用。不过,如果您可以在代码中添加简短的注释,这样我就可以理解正在发生的事,这样我就可以根据将来的需要修改它。再次感谢在里面
$ awk '/^CC /{FS=":"; $0=$0; a=$2} /^FT /{FS="[ ;.]+"; $0=$0;print a,$(NF-1),$NF,$5}' file
 chr22 23144712 23145380 SP1
 chr22 23147445 23148194 ER-ALPHA
 chr22 23150853 23151108 C/EBPBETA
 chr3 23147445 23148194 ER-ALPHA
 chr3 23151393 23151582 CTCF