【问题标题】:remove the first 15 characters from every other line in a file删除文件中每隔一行的前 15 个字符
【发布时间】:2015-05-13 22:12:33
【问题描述】:

我有一些看起来像这样的 txt 文件(它们包含 DNA 序列和示例代码):

>SRR1502445.1
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCAACACAGGGGGATAGGNNNNNNNNNNNNNNNNNNNNNNN
>SRR1502445.2
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNN
>SRR1502445.3
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNN
>SRR1502445.4
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNNNNNNNNNN

我想删除文件中每隔一行的前 15 个字符。这将从第二、第四、第六、第八行(等)中删除字符串GACTACACGTAGTAT

例如 cut 命令可以删除每行的前 15 个字符:

cut -c 1-15 /path/to/file.txt

我想只申请每隔一行,从第二行开始。

【问题讨论】:

  • 请发布您尝试过的代码,以及运行代码时会发生什么。
  • 使用 Biopython 或 Bioperl 或 Biojava 或 BioETC 解析 falta,两行代码......
  • @JoseRicardoBustosM。我宁愿找到一个不涉及安装这些软件包之一的解决方案,因为可能有使用基本终端命令的解决方案。
  • 你需要截断 fasta 和 qual 文件
  • @colin,请您解决 Jose Ricardo Bustos M. re: “在 FASTA 格式中的评论,它并不总是一行标题,然后一行序列...” 这适用于您的情况吗?因为如果是这样的话,任何被编码为显式跳过每一行的解决方案都可能失败!

标签: bash unix terminal bioinformatics qiime


【解决方案1】:

如果您不介意使用 sed 并假设其他行以 > 开头,那么以下将删除其他行的前 15 个连续大写字符“A-Z”:

sed 's/^[A-Z]\{15\}//' file > new_file

或者,就地编辑(GNU sed)使用-i

sed -i 's/^[A-Z]\{15\}//' file

或者,就地编辑(BSD sed)使用-i ''

sed -i '' 's/^[A-Z]\{15\}//' file

或者,备份它:

sed -i.bak 's/^[A-Z]\{15\}//' file

示例:

$ cat file
>SRR1502445.1
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCAACACAGGGGGATAGGNNNNNNNNNNNNNNNNNNNNNNN
>SRR1502445.2
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNN
>SRR1502445.3
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNN
>SRR1502445.4
GACTACACGTAGTATACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNNNNNNNNNN
$ sed 's/^[A-Z]\{15\}//' file
>SRR1502445.1
ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCAACACAGGGGGATAGGNNNNNNNNNNNNNNNNNNNNNNN
>SRR1502445.2
ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNN
>SRR1502445.3
ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNN
>SRR1502445.4
ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTTGAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTGGAAGCGGGTTCCAAGGCACACAGGGGATAGGNNNNNNNNNNN
$ 

【讨论】:

  • 有没有办法做到这一点,这样我就不必实际输入要删除的序列,而是只删除前 15 个字符,不管它们是什么?通常需要删除的是前 15 个字符,但不一定是 GACTACACGTAGTAT
  • @colin 所有以> 开头的行是否总是少于15 个字符?如果是,您可以使用以下内容:sed 's/^.\{15\}//' file
  • 不幸的是,以 > 开头的行最多可以超过 17 个字符。
  • @colin 假设每隔一行以> 开头,那么以下将删除其他行的前 15 个大写字符“A-Z”:sed 's/^[A-Z]\{15\}//' file
  • @colin 尝试:sed 's/^[A-Z]\{3\}//' file
【解决方案2】:

你可以试试

sed '0~2s/^.\{15\}//g' filename

0~2 每 2 行取一次

^.\{15\}

查找前 15 个字符

sed 命令将它们替换为空!

【讨论】:

  • 这会产生以下错误:sed: 1: "0~2s/^.\{15\}//g": invalid command code ~
  • 您使用的是哪种风格的 unix?更重要的是,它可能是复制粘贴错误。在编写代码时尝试使用波浪号!对我来说效果很好!
  • 我在 mac osx 上使用终端 - 刚刚将代码手动输入终端,我仍然收到相同的错误:sed: 1: "0~2/^.\{15\}//g": invalid command code ~,这很糟糕,因为您的代码似乎可以概括为大多数情况!
  • @colin,OS X 使用 BSD sed,它不支持 Dipak 提供的 0~2s 部分中的 ~,尽管 GNU sed 支持。我为您提供的sed 命令不需要使用该范例,也不会触及标题行,因为它们中有数字字符,而我提供的sed 指令只能从中删除前 15 个连续的大写字母字符以大写字母开头的行,因此无需指示sed 跳过行。
  • 再次考虑检查如何格式化您的答案。使用{} 按钮打印代码。
【解决方案3】:

以下脚本可能会对您有所帮助,它需要两个参数: 1. 原始文件(从中进行转换) 2. 保存结果的文件。

#!/bin/bash
# call this script and pass two arguments:
# ./script FROM_FILE TO_FILE
FROM=$1
TO=$2

i=1;
while IFS=$'\n' read line; do
    ((i++)); 
    # skip 2,4,6, ..., nth lines 
    [ $((i % 2)) -eq 0 ] && (echo -n $line >> $TO; continue);
    echo ${line:15} >> $TO
done < $FROM

【讨论】:

  • 虽然它确实删除了文件中每隔一行的前 15 个字符,但它也删除了从第一行开始的整个每隔一行!
  • 现在它什么也不输出了!在发布之前测试您的代码!
  • 你说得对——我的错。再试一次,亲爱的。
  • 我强烈建议您重新阅读 colin 想要的内容... "我想删除文件中每隔一行的前 15 个字符。这将从第二个中删除字符串 GACTACACGTAGTAT,第四、第六、第八行(等等)。”
  • 您提出的解决方案只有在 colin 的文件中填充了相同的字符串时才有效。他本可以很好地使用一个简单的文本编辑器来解决这个问题;)然而,我发现您的解决方案优雅而聪明。
【解决方案4】:

您需要擦除文件 fasta 的第一个碱基并进行分析,而我使用 QIIME 找到了一个解决方案,这是一个使用 python 和 biopython 的解决方案:

from Bio import SeqIO

file_fasta = open("test.fasta")
file_qual = open("test.qual")

iterator_fasta = SeqIO.parse(file_fasta, "fasta")
iterator_qual = SeqIO.parse(file_qual, "qual")

size_trim = 15

output_fasta = open("trim.fasta","w")
for seq in iterator_fasta:
  if len(seq) <= size_trim:
    raise NameError('len seq less or equal than trim size')
  seq.seq = seq.seq[size_trim:]
  output_fasta.write(seq.format("fasta"))

output_fasta.close()

output_qual = open("trim.qual","w")
for seq_qual in iterator_qual:
  if len(seq_qual.letter_annotations['phred_quality']) <= size_trim:
    raise NameError('len qual less or equal than trim size')
  seq_qual.letter_annotations['phred_quality'] = seq_qual.letter_annotations['phred_quality']
  output_qual.write(seq_qual.format("qual"))

output_qual.close()

你进入 trim.fasta

>SRR1502445.1 ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTT GAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTG GAAGCGGGTTCCAAGGCAACACAGGGGGATAGGNNNNNNNNNNNNNNNNNNNNNNN >SRR1502445.2 ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTT GAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAGACGGTTGG AAGCGGGTTCCAAGGCACACAGGGGATAGGNNN >SRR1502445.3 ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTT GAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTG GAAGCGGGTTCCAAGGCACACAGGGGATAGGNNN >SRR1502445.4 ACGAGTGCGTTCCTGCGCTTATTGATATGCTTAAGTTCAGCGGGTAGTCTCACCCGATTT GAGGTCAAGGTTTGTGGGTCGAGTCACAACTCGAACATCGTCTTTGTACAAAGACGGTTG GAAGCGGGTTCCAAGGCACACAGGGGATAGGNNNNNNNNNNN

编辑:

使用qiime,我推荐使用split_libraries,它会进行修剪和检查质量....truncate_fasta_qual_files.py 只选择前B 个碱基,修剪最后一个碱基,否则会超出预期。

【讨论】:

  • 你也应该消除歧义
  • @colin 使用 qiime 存在 split_libraries,此脚本进行修剪
  • 它不会修剪 split_libraries 中的前 n 个碱基 - 它只能删除已知序列,例如您的条形码。我将研究 truncate_fasta_qual_files.py。请详细说明“您也应该消除歧义”的意思。
  • @colin 最后删除了 N
【解决方案5】:

sed 的单行替代方案是awk

给定一个名为foo.fa 的交替行元素FASTA 文件,您可以使用substr() 去除序列字符串的前15 个字符:

$ awk '/^#/ {next} /^>/ { print $0 } /^[^>]/ { print substr($0, 16, length($0) - 15) }' foo.fa > foo.filtered.fa

由于 awk 使用从 1 开始的索引,substr() 中的起始位置参数是 16。

除了提供代码来分别处理交替行之外,awk 的另一个优点是它有时可以比sed 运行得更快。考虑到常见生物信息学平台之间sed 的差异,另一个优势是可移植性。

因此,如果您计划大量执行此操作或处理“全基因组”规模的文件,您也可以研究这种方法。

【讨论】:

  • Alex,你能解释一下,你的单线在做什么吗?
  • /^#/ {next} 指令在指定的正则表达式模式^&gt;^[^&gt;] 上应用两个不同的代码块,它们分别表示交替行FASTA 文件中的标题行和序列行。 ^&gt; 块只打印标题行($0),而^[^&gt;] 块打印序列行的子字符串(同样,$0),起始参数为15,长度参数为行长,减 14。这有效地去除了前 15 个字符,无论它们是什么。
  • 抱歉,我犯了一个错误。正确的起始索引是 16,而不是 15。
【解决方案6】:

使用正则表达式和 perl 或 awk,

perl(写一个脚本,扩展它来检测其他正则表达式,

my $pattern=$ARGV[1]||"GACTACACGTAGT";
#provide any gene sequence prefix, and pattern removes that prefix
while (<>) {
    #explicit check for non-gene/header pattern
    if( $_ =~ /^[\>\;]/ ) {
        print $_;
    }
    #check for the specific header pattern provided, for example
    elsif( $_ =~ /^SRR1502445/ ) {
        print $_;
    }
    #check for the gene pattern given
    elsif( $_ =~ /^$pattern(.*)/ ) {
        print "$1\n";
    }
    else {
        print $_;
    }
}

perl -lane,

perl -lane 'if( $_ =~ /^GACTACACGTAGT(.*)/ ) {print "$1\n";} else {print $_; }'

awk,

/SRR1502445/ { print $0; }
/^GACTACACGTAGTAT/ { print substr($0,16); }

适用于任何 linux/unix 机器,也适用于 cygwin。


文件格式好像是FASTA,这里有说明FASTA Specification

【讨论】:

  • 您应该会看到 colin 对我的回答发表的第一条评论。前 15 个字符并不总是“GACTACACGTAGTAT”,因此您的答案与我的第一个字符相同。
  • 在FASTA格式中,并不总是一行header后一行sequence,通常有几行sequence,OP只需删除几行sequence中的前15个字母
  • OP 要求提供一种解决方案,该解决方案将每隔一行删除前 15 个字符 - 这从您的 cmets 表明对文件格式的了解不完整。但是,我提供的解决方案使用正则表达式,并且将解决上述问题以及更普遍的问题,即如何识别基因模式与标头模式(至少对于 perl 脚本版本)。
  • @ChuckCottrill,我想你可能误解了或者没有遵循所有相关的 cmets。标题行可以是不同的长度和值以及 DNS 序列,这与示例中的 15 个字符不同。此外,您发布的 perl 脚本中包含 else if,不应该是 elsif 吗?我问是因为编写的脚本会在那里引发错误。此外,在perl -lane 行中,您有{print "$1\n";},不应该只是{print "$1";} 吗?否则,它会在每个 DNS 序列之后插入一个空白,并且在 OP 中没有这样显示。
猜你喜欢
  • 1970-01-01
  • 2015-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 2012-01-19
相关资源
最近更新 更多