查找并替换文件夹中所有文件的特殊模式

查找并替换文件夹中所有文件的特殊模式

我有一系列采用常见生物信息学格式 (FASTA) 的文件,其中包含以下字符串:1 个特殊字符“">”、作为样本名称的文本(字符串长度各不相同,可以包含数字或字母)以及额外的数字由生物信息学管道添加。我在 Mac OSX 上使用 Bash。

我想使用特殊模式查找并替换文本字符串,以消除样本名称后面的所有数字(此处的样本是“Tsuc2”)。到目前为止,我发现执行此操作的最佳方法是在 TextEdit 中手动使用“数字”的特殊模式。这可行,但理想情况下我想提出一个for循环查找文件夹中的所有文件,而不是打开它们并逐一执行查找替换操作。我想它会使用 grep 或 sed。我遇到的问题是额外数字的数量各不相同,并且样本名称和需要删除的数字之间没有分隔符。

我最好的猜测是

$ for FILE in *_R2.fastq.gz.fa; do sed -i 's\[b$FILE]\[0-9]\b/$FILE/g'; done

这不起作用(可能出于明显的原因)。有任何想法吗?

编辑以解决评论:是的,这是一个 fasta 文件(基本上与 .txt 相同,但独特之处在于格式始终遵循“>”+“样本名称”+“核苷酸序列”。它没有压缩。它被转换来自压缩的 fastq 文件,仅包含修剪的序列,而不包含碱基检出分数。

我无法将问题重新表述为“删除所有行中的所有数字”,因为样本名称包含数字(“Tsuc2”)。我能够轻松地从单个文件中删除多余的数字,我的问题是“当文件之间要保留的字符和数字数量不同并且没有文件时,如何查找和替换文件夹中所有文件的字符串”样本名称中的数字与管道表面添加的数字之间的分隔符。”

我已将文件布局提供为图像,因为此处的文本编辑器将“>”解释为缩进,但我可以将其粘贴到下面的括号内。

>Tsuc21
TTAAGTTCAGCGGGTATTCCTACCTGATCCGAGGTCAACCATTAAAATTGGGGGGTTTAGCGGCTGAGAGCTGCAACACC
TAACCAAAGCGAGAAAAAAATTACTACGCTAAGAGGATATTACAGATCCGCCGTTGTATTTCAGGAACTACAATACAGTA
>Tsuc22
TTAAGTTCAGCGGGTATTCCTACCTGATCCGAGGTCAACCATTAAAATTGGGGGGTTTAGCGGCTGAGAGCTGCAACACC
TAACCAAAGCGAGAAAAAAATTACTACGCTCAGAGGATATTACAGATCCGCCGTTGTATTTCAGGAACTACAATACAGTA
GATTCCCAACACTAAGCTAGGCTTAAGGGT
>Tsuc23
TTAAGTTCAGCGGGTATTCCTACCTGATCCGAGGTCAACCTTGTAAAAATTACAGTGGTGTTTAACGGCCGAGAACCGCC
GAGTCTCCCAAGCGAGAAAGTAAACTACTACGCTCGGAGCCACGGAGGGCCCTCCACTGATCTTGGGGGCCTGCGAGAGT
TTTTAATTAACGCTCGCAGAGGGCCCCAAC
>Tsuc24
TTAAGTTCAGCGGGTATTCCTACCTGATCCGAGGTCAACCATTAAAATTGGGGGGTTTAGCGGCTGAGAGCTGCAACACC
TAACCAAAGCGAGAAAAAAATTACTACGCTCAGAGGATATTACAGATCCGCCGTTGTATTTCAGGAACTACAATACAGTA
GATTCCCAACACTAAGCTAGGCTTAAGGGT

包含多行数据的 FASTA 文件的图像,其中每行无限添加一个附加数字(有时是单个数字,最多可达数万位数字)

答案1

如果您向我们展示实际的文件名,我可以对此进行调整,但假设您的示例名称始终是_文件名中第一个字符串之前的最长字符串,您可以执行以下操作:

for file in *_R2.fastq.gz.fa; do
   sed -i '.bak' "s/\(>${file%%_*}\).*/\1/" "$file"
done

${file%%_*}更一般地说,or语法${var%%pattern}是 bash 字符串操作,用于“从字符串末尾删除模式的最长匹配项”。在这里,该模式_*将删除从第一个 _ 到字符串末尾的所有内容,留下样本名称。请注意,-i '.bak'这将确保您sed为每个修改的文件创建备份副本。如果你不想这样,你可以使用-i '',但你不能-i在 BSD 上单独使用sed(这是 macOS 所拥有的)。最后,该sed表达式捕获我们想要保留的部分,使其成为\1,并删除其余部分。


如果您只想删除一个递增的数字(看起来就是这样),那么您想1从第一个序列 ID 行、2第二个序列 ID 行等中删除,您可以更直接地执行此操作,如下所示:

perl -i '.bak' -pe '$k++ if />/; s/(>.+?)$k.*/$1/' *_R2.fastq.gz.fa

诀窍是$k每次>看到 a 时我们就加一,然后保留 a 值之前的任何内容$k并删除其余的内容。

相关内容