如何使用文件中的行作为 grep 的关键字?

How to use lines in a file as keyword for grep?

我在这里和其他网站上搜索了很多问题,人们提出了可以解决我的问题的建议,但我认为我的代码有一些我无法识别的错误。

我有 24 个来自 NGS 测序的 .fasta 文件,长度为 150bp。每个文件大约有 1M 次读取。读数来自靶向测序,我们在载体上电镀了感兴趣基因的 cDNA 和独特的条形码序列。我需要查看测序文件是否存在与特定基因对应的条形码序列。

我有一个 .txt 条形码序列列表,我想将其传递给 grep 以在 .fasta 文件中查找条形码。我已经尝试了很多这个命令的变体。我可以单独给每个条形码 grep 但这太耗时了,我知道可以给它一个条形码序列列表并在每个 .fasta 中搜索每个条形码并记录在每个文件中找到每个条形码的次数。

这是我的代码,我分别给它每个条形码:

# Barcode 33
mkdir --mode 755 $dir/BC33
FILES="*.fasta"
for f in $FILES;      do                      
cat "$f" | tr -d "\n" | tr ">" "\n" | grep 'TATTAGAGTTTGAGAATAAGTAGT' > $dir/BC33/"$f"
                      done

我尝试对其进行调整,这样我就不必单独输入每个条形码序列:

dir="/home/lozzib/AG_Barcode_Seq/"
cd $dir
FILES="*.fasta"
for f in $FILES;      do                                              
cat "$f" | tr -d "\n" | tr ">" "\n" | grep -c -f BarcodeScreenSeq.txt | sort > $dir/Results/"$f"
echo "Finished $f"
                      done

但它不是在搜索条形码序列。通过这次迭代,它只是在 /Results 目录中返回空的新文件。我还尝试了一个嵌套循环,我试图使条形码序列成为一个像 $FILES 一样变化的变量,但这只是给了我一个新文件,其中包含我的 .fasta 文件的名称:

dir="/home/lozzib/AG_Barcode_Seq/"
cd $dir    
FILES="*.fasta"
for f in $FILES;      do                        
for b in `cat /home/lozzib/AG_Barcode_Seq/BarcodeScreenSeq.txt`; do                   
cat "$f" | grep -c "$b" | sort > $dir/"$f"_Barcode
                      done   ;
                      done    

我想要一个包含以下内容的输出 .txt 文件:

<barcode sequence>: <# of times that bc was found> 

对于每个 .fasta 文件,因为我想将所有样本放在一起形成一个大的 excel sheet,它显示每个条形码以及在每个样本中找到它的次数。

请帮忙,我已经尝试了所有我能想到的方法。

编辑

这是 BarcodeScreenSeq.txt 文件的样子。它只是一个 txt 文件,其中每一行都是一个条形码序列:

head BarcodeScreenSeq.txt 
TATTATGAGAAAGTTGAATAGTAG 
ATGAAAGTTAGAGTTTATGATAAG 
AATAGATAAGATTGATTGTGTTTG 
TGTTAAATGTATGTAGTAATTGAG 
ATAGATTTAAGTGAAGAGAGTTAT 
GAATGTTTGTAAATGTATAGATAG 
AAATTGTGAAAGATTGTTTGTGTA 
TGTAAGTGAAATAGTGAGTTATTT 
GAATTGTATAAAGTATTAGATGTG 
AGTGAGATTATGAGTATTGATTTA

编辑

lozzib@gliaserver:~/AG_Barcode_Seq$ file BarcodeScreenSeq.txt
BarcodeScreenSeq.txt: ASCII text, with CRLF line terminators

您可以一次读取文本文件一行,然后使用重定向分别处理每一行,如下所示:

for f in *.fasta; do 
    while read -r seq; do
        grep -c "${seq}" "${f}" > "${dir}"/"${f}"_Barcode
    done < /home/lozzib/AG_Barcode_Seq/BarcodeScreenSeq.txt
done

Windows 行结尾

您的 BarcodeScreenSeq.txt 有 windows 行结尾。每行以特殊字符 \r\n 结尾。 Linux grep 等工具仅处理 linux 行结尾 \r 并解释您的文件 ...

TATTATG\r\n
ATGAAAG\r\n
...

寻找模式 TATTATG\rATGAAAG\r、...(注意末尾的 \r)。因为 \r 没有匹配项。

或者: 转换一次文件再见 运行 dos2unix BarcodeScreenSeq.txtsed -i 's/\r//g' BarcodeScreenSeq.txt。这将更改您的文件。
或: 将以下脚本中的每个 BarcodeScreenSeq.txt 替换为 <(tr -d '\r' < BarcodeScreenSeq.txt)。这不会更改文件,但会随着文件被一遍又一遍地转换而产生更多开销。

命令

grep -c 只有一个计数器。如果您一次传递多个搜索模式(例如使用 -f BarcodeScreenSeq.txt),您仍然只能得到所有模式的一个数字。

要单独计算每个模式的出现次数,您可以使用以下技巧:

for file in *.fasta; do
    grep -oFf BarcodeScreenSeq.txt "$file" |
    sort | uniq -c |
    awk '{print  ": "  }' > "Results/$file"
done

grep -o 会将每个匹配项打印为一行。
sort | uniq -c 将计算每行出现的频率。
awk 仅用于将格式从 #matches pattern 更改为 pattern: #matches

好处:命令应该相当快。
缺点: 来自 BarcodeScreenSeq.txt 而在 $file 中找不到的模式根本不会被列出。您的结果将省略 pattern: 0.

形式的行

如果您确实需要 pattern: 0 形式的行,您可以使用另一个技巧:

for file in *.fasta; do
    grep -oFf BarcodeScreenSeq.txt "$file" |
    cat - BarcodeScreenSeq.txt |
    sort | uniq -c |
    awk '{print  ": " ( - 1) }' > "Results/$file"
done

cat - BarcodeScreenSeq.txt 将在 grep 的输出末尾插入 BarcodeScreenSeq.txt 的内容,使得 #matches 比应有的大 1。该数字由 awk.

更正