编辑:我在 Linux 集群中工作。
我有一个巨大的文件,在第一列中列出了一个 ID,第二个是原始文件中列的组合,在第 4-5-6 列中复制。输入文件如下所示:
1 1:71:T:C 0 71 C T
1 1:71:T:A 0 71 A T
1 1:72:GTGTGTGTT:G 0 72 G GTGTGTGTT
1 1:75:T:C 0 75 C T
1 1:75:T:* 0 75 * T
1 1:76:GTGTT:G 0 76 G GTGTT
1 1:76:GTGTT:* 0 76 * GTGTT
1 1:83:C:CAT 0 83 CAT C
1 1:87:CGT:C 0 87 C CGT
1 1:87:C:CGTGTGT 0 87 CGTGTGT C
U U:19874536:G:A 0 19874536 A G
U U:19874560:G:A 0 19874560 A G
U U:19874575:C:T 0 19874575 T C
U U:19874577:T:G 0 19874577 G T
U U:19874587:CA:C 0 19874587 C CA
U U:19874587:CAA:C 0 19874587 C CAA
U U:19874602:C:T 0 19874602 T C
U U:19876478:T:C 0 19876478 C T
U U:19876534:C:A 0 19876534 A C
U U:19876568:T:C 0 19876568 C T
22 X:29:G:GT 0 29 G GT
22 X:96:T:A 0 96 A T
22 X:146:A:G 0 146 G A
22 X:167:A:T 0 167 T A
22 X:168:T:C 0 168 C T
22 X:244:C:T 0 244 T C
22 X:253:C:A 0 253 A C
22 X:254:C:A 0 254 A C
22 X:330:G:T 0 330 T G
22 X:371:GGCGTTTACGT:G 0 371 G GGCGTTTACGT
.
.
.
我正在尝试检查第一列(ID)如何与第二列中的原始 ID 匹配,所以我只想打印 matches 原始 ID 列表的第一行(在第二列中)。我希望这很清楚!我看到 https://stackoverflow.com/questions/50263627/how-to-extract-only-first-line-that-matches-each-pattern-from-a-file,我认为它应该能够帮助我,但我不熟悉 awk 并且我不知道如何编辑它所以 match 仅指第二列中的 ID(在“:”之前)。
编辑:预期输出:
1 1:71:T:C 0 71 C T
U U:19874536:G:A 0 19874536 A G
22 X:29:G:GT 0 29 G GT
.
.
.
回答1
Perl 解决方案:
perl -F'/[\s:]+/' -lane 'BEGIN { %matches = ( 22 => "X", ); } print if ( ( $F[0] eq $F[1] || $F[1] eq $matches{ $F[0] } ) && !$seen{ $F[0] }++ ); ' infile > outfile
Perl 单行器使用这些命令行标志:-e
:告诉 Perl 查找内联代码,而不是在文件中。-n
:循环一次输入一行,默认将其分配给 $_
。-l
:在执行代码之前剥离输入行分隔符(默认为 *NIX 上的 "\n"
)行,并在打印时附加它。-a
: 将 $_
拆分为数组 @F
上的空白或 -F
选项中指定的正则表达式。-F'/[\s:]+/'
:在空格或 :
上拆分为 @F
,重复 1 次或多次,而不是在空格上。
%matches = ( 22 => "X", );
- 创建哈希 %matches
,它将匹配的 ID 从第 1 列映射到第 2 列。为了加快速度,这被放置在 BEGIN { ... }
块中,该块仅在脚本开头执行一次,在后续代码之前运行,它针对每个输入行运行。!$seen{ $F[0] }++
:仅对于第一列中每个 value 的第一次出现为 true。