我在 Linux 机器上有一个如下所示的文件,但它gene_id
是错误的。所以我想将"PB"
中的字符串替换为同一行中的gene_id
。transcript_id
$ cat try.gff
transcript 30351 32332 . + . gene_id "PB"; transcript_id "PB.1.66";
exon 30351 31677 . + . gene_id "PB"; transcript_id "PB.1.59";
exon 31758 31871 . + . gene_id "PB"; transcript_id "PB.1.40";
exon 31968 32178 . + . gene_id "PB"; transcript_id "PB.1.30";
exon 32257 32332 . + . gene_id "PB"; transcript_id "PB.1.20";
transcript 30351 32332 . + . gene_id "PB"; transcript_id "PB.28.309";
exon 30351 31677 . + . gene_id "PB"; transcript_id "PB.58.900";
exon 31758 31871 . + . gene_id "PB"; transcript_id "PB.10000.1001";
exon 31968 32178 . + . gene_id "PB"; transcript_id "PB.19897.1087541";
exon 32257 32332 . + . gene_id "PB"; transcript_id "PB.1.11";
预期结果
transcript 30351 32332 . + . gene_id "PB.1"; transcript_id "PB.1.66";
exon 30351 31677 . + . gene_id "PB.1"; transcript_id "PB.1.59";
exon 31758 31871 . + . gene_id "PB.1"; transcript_id "PB.1.40";
exon 31968 32178 . + . gene_id "PB.1"; transcript_id "PB.1.30";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.20";
transcript 30351 32332 . + . gene_id "PB.28"; transcript_id "PB.28.309";
exon 30351 31677 . + . gene_id "PB.58"; transcript_id "PB.58.900";
exon 31758 31871 . + . gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon 31968 32178 . + . gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.11";
我设法获得了正确的文本以替换为代码awk -F";" '{gsub(" transcript_id ","");print $2}' try.gff | sed 's/"//g' | cut -d '.' -f 1,2
PB.1
PB.1
PB.1
PB.1
PB.1
PB.28
PB.58
PB.10000
PB.19897
PB.1
我怎样才能更换零件"PB"
中的零件gene_id
?
答案1
sed
在每个 Unix 机器上的任何 shell 中使用 any :
$ sed 's/\(.*gene_id "\)[^"]*\(.*"\([^.]*\.[^.]*\).*\)/\1\3\2/' try.gff
transcript 30351 32332 . + . gene_id "PB.1"; transcript_id "PB.1.66";
exon 30351 31677 . + . gene_id "PB.1"; transcript_id "PB.1.59";
exon 31758 31871 . + . gene_id "PB.1"; transcript_id "PB.1.40";
exon 31968 32178 . + . gene_id "PB.1"; transcript_id "PB.1.30";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.20";
transcript 30351 32332 . + . gene_id "PB.28"; transcript_id "PB.28.309";
exon 30351 31677 . + . gene_id "PB.58"; transcript_id "PB.58.900";
exon 31758 31871 . + . gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon 31968 32178 . + . gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.11";
在正则表达式部分中,每个\(
都会启动一个捕获组,该捕获组由匹配的\)
.在替换部分中,every\<digit>
指的是与捕获组中的正则表达式段匹配的字符串。 so\1
指的是匹配的字符串\(.*gene_id "\)
等等。其余的只是基本的正则表达式段(例如,.*
表示任何字符的 0 次或多次重复,[^"]*
表示除 之外的任何字符的零次或多次重复"
,以及\.
表示文字.
)。
答案2
使用sed
$ sed 's/"[A-Z]\+\("[^"]*\(.*\)\..*\)/\2\1/' input_file
transcript 30351 32332 . + . gene_id "PB.1"; transcript_id "PB.1.66";
exon 30351 31677 . + . gene_id "PB.1"; transcript_id "PB.1.59";
exon 31758 31871 . + . gene_id "PB.1"; transcript_id "PB.1.40";
exon 31968 32178 . + . gene_id "PB.1"; transcript_id "PB.1.30";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.20";
transcript 30351 32332 . + . gene_id "PB.28"; transcript_id "PB.28.309";
exon 30351 31677 . + . gene_id "PB.58"; transcript_id "PB.58.900";
exon 31758 31871 . + . gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon 31968 32178 . + . gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.11";
答案3
使用乐(以前称为 Perl_6)
简单的方法(假设 TSV 文件gff
格式):
raku -e 'my @a = lines>>.split("\t").flat; @a[7,17,27...*] = @a[9,19,29...*]; \
@a[7,17,27...*].=comb(/ <alpha>+ \. <digit>+ /).=map(q["] ~ * ~ q["]); \
.put for @a.rotor(10)>>.join("\t");'
上面的代码只是将每个选项卡和十个元素拆分line
为\t
一个flat
完全线性的数组(10 行 x 10 列 = 100 个元素)。每个第 8 列gene_id
(零索引 = 7)都会被第 10 列transcript_id
(零索引 = 9)覆盖。只要您给它足够的提示,Raku 就会计算出索引序列的其余部分。
transcript_id
复制完整内容后,就可以很简单地comb
取出<alpha>+ \. \d+
所需的字符,q["] ~ * ~ q["]
将它们用引号引起来,然后rotor
每 10 个元素即可重建 10 x 10 表。
纯粹的正则表达式方式(更难):
~$ raku -pe 's/ <?after ^ .+? gene_id \s \" > (.+?) (\"\; \s transcript_id \s \") (<alpha>+ \. \d+) <?before \.> /$2$1$2/;' try.gff
或者
~$ raku -pe 's/ <?after ^ .+? gene_id \s \c[QUOTATION MARK] > (.+?) (\c[QUOTATION MARK] \; \s transcript_id \s \") (<alpha>+ \. \d+) <?before \.> /$2$1$2/;' try.gff
这里使用 Raku 的-pe
自动打印逐行标志,与熟悉的s///
替换运算符结合使用。搜索五个正则表达式原子,并用括号捕获三个原子:
- 零宽度正向后查找,
<?after … >
目标^
是字符串开头gene_id \s \"
(包括尾随空格和引号), - [捕获为
$0
]非贪婪的.+?
任意字符一次或多次,即要被丢弃的gene_id
本身, - [捕获为] 包含该行部分的
$1
文本(包括周围的空格和标点符号),transcript_id
- [捕获为]的
$2
所需部分,然后<alpha>+ \. \d+
transcript_id
- 零宽度正前瞻
<?before … >
,在第二个点之前停止前面的捕获\.
。
最后在替换中,$2
用captured来替换$0
capture。和$1
捕获$2
将恢复到正常位置。
输入示例:
transcript 30351 32332 . + . gene_id "PB"; transcript_id "PB.1.66";
exon 30351 31677 . + . gene_id "PB"; transcript_id "PB.1.59";
exon 31758 31871 . + . gene_id "PB"; transcript_id "PB.1.40";
exon 31968 32178 . + . gene_id "PB"; transcript_id "PB.1.30";
exon 32257 32332 . + . gene_id "PB"; transcript_id "PB.1.20";
transcript 30351 32332 . + . gene_id "PB"; transcript_id "PB.28.309";
exon 30351 31677 . + . gene_id "PB"; transcript_id "PB.58.900";
exon 31758 31871 . + . gene_id "PB"; transcript_id "PB.10000.1001";
exon 31968 32178 . + . gene_id "PB"; transcript_id "PB.19897.1087541";
exon 32257 32332 . + . gene_id "PB"; transcript_id "PB.1.11";
示例输出:
transcript 30351 32332 . + . gene_id "PB.1"; transcript_id "PB.1.66";
exon 30351 31677 . + . gene_id "PB.1"; transcript_id "PB.1.59";
exon 31758 31871 . + . gene_id "PB.1"; transcript_id "PB.1.40";
exon 31968 32178 . + . gene_id "PB.1"; transcript_id "PB.1.30";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.20";
transcript 30351 32332 . + . gene_id "PB.28"; transcript_id "PB.28.309";
exon 30351 31677 . + . gene_id "PB.58"; transcript_id "PB.58.900";
exon 31758 31871 . + . gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon 31968 32178 . + . gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon 32257 32332 . + . gene_id "PB.1"; transcript_id "PB.1.11";