使用mac命令行,我想grep多个文件并将输出保存到不同的列。
以下是我的一个文件的示例ncbi.nlm.nih.gov/nuccore/NZ_AP013294(点击'发送到','文件'保存格式为'完整的genbank文件')。我有~2000个。我只想要LOCUS(这对于每个文件都是唯一的,并且总是有一个)然后每次都有tRNA-,例如tRNA-Glu(整个文件中出现tRNA-,其中可能有0到200个)。
当我在其中一个文件上执行此操作时
grep -e "LOCUS-" -e "tRNA-" *.gbff > output.txt
但我希望output.txt
文件包含列,每个*.gbff
文件一个:
LOCUS XXXX LOCUS XXXX
tRNA-Glu tRNA-Asn
tRNA-Ser tRNA-Ile
tRNA-Glu
...等
答案 0 :(得分:2)
更新了答案
我认为我的原始方法对于您拥有的文件数量而言资源过于密集,因此这是一个不太密集的版本:
#!/bin/bash
# Don't barf of no matching files, and allow upper and lower case
shopt -s nullglob nocaseglob
# Loop through all ".txt" files whose names start with "seq"
j=0
for f in seq*txt; do
# Generate output file name
printf -v out "Z%05d.tmp" $j
grep -E "LOCUS\s*NZ_AP013294|tRNA" "$f" > "$out"
((j=j+1))
done
# Paste all output files together in columns
paste Z*tmp > result.txt
# Remove temp files
rm Z*tmp
我只命名所有以" Z"开头的临时文件。因此它们只会在文件浏览器的最后显示。
因此,将上述内容保存在名为" go"的文件中。在您的HOME目录中,然后使用以下命令使其可执行:
chmod +x $HOME/go
然后你可以通过以下方式在任何目录中运行它:
cd some/place/where/your/files/are
$HOME/go
原始答案
我认为这给了你想要的东西:
parallel 'grep "term" {} > {#}.tmp' ::: *txt ; paste *tmp ; rm *tmp
示例输出
term1 term1
term3 term2
term3
那说...... "在名称以term
结尾的所有文件中查找txt
,保存1.tmp
中第一个的输出,第二个在2.tmp
等等。最后,将所有临时文件粘贴到列中并将其删除。"
您需要知道,使用 GNU Parallel ,{}
代表"当前参数/文件" 和{{ 1}}代表"当前作业编号" ,最后{#}
将参数与要应用的命令分开。
您也可以在没有临时文件的情况下执行此操作。使用 GNU Parallel 作业编号为:::
输出的每一行添加前缀,然后通过 Perl 中的批次删除作业编号并将其替换为8 *很多空间:
grep
所有Mac都附带Perl 。
对于任何感兴趣的人,这是Schwartzian Transform或Lisp decorate-sort-undecorate 习语的变体。
我使用自制安装 GNU Parallel :
parallel --tag-string {#} 'grep "term" {}' ::: *txt | perl -plne 's/^(\d+)\s*/" " x (8*($1-1))/e'
term1
term3
term1
term2
term3
虽然它也可以在没有自制的情况下非常简单地安装,因为仅 Perl 脚本,并且所有Mac都附带 Perl 强>:
brew install parallel
答案 1 :(得分:1)
你的问题不清楚,但考虑到你的要求可能的解释,这可能是你想要的:
awk '
/LOCUS/ {
locus[++numCols] = $0
}
/tRNA/ {
rnas[++rowNrs[numCols],numCols] = $0
numRows = (rowNrs[numCols] > numRows ? rowNrs[numCols] : numRows)
}
END {
for (colNr=1; colNr<=numCols; colNr++) {
printf "%s%s", locus[colNr], (colNr<numCols ? OFS : ORS)
}
for (rowNr=1; rowNr<=numRows; rowNr++) {
for (colNr=1; colNr<=numCols; colNr++) {
printf "%s%s", rnas[rowNr,colNr], (colNr<numCols ? OFS : ORS)
}
}
}
' *.txt
当然未经测试,因为您没有提供样本输入/输出,我们可以测试。
如果那不是你想要的,那么你想要的任何东西都同样微不足道但是你必须首先告诉/告诉我们你的问题是什么,以便为它找到解决方案。
答案 2 :(得分:1)
使用awk的模式匹配来查找单个LOCUS和任何tRNA提及。
使用awks字段拆分作为第二项
免费获取locus登录将tRNA产品(如果有的话)拆分成引号并将它们与基因座加入相关联。
跟踪一个基因座的最大tRNA数量,这将是输出的行数(加上标题)
在处理命令行上给出的所有文件中的所有GenBank记录之后。
输出每个基因座的加入作为标题 然后为每一行尽可能 输出在其基因座加入下相关的任何tRNA产物。
脚本:
#! /usr/local/bin/gawk -f
/^LOCUS /{RefSeq = $2}
/^ \/product="tRNA-/{
split($1, tRNA, "\"");
head[RefSeq]++;
LOCUS[RefSeq,head[RefSeq]] = tRNA[2]
if(head[RefSeq] > rows)
rows = head[RefSeq]
}
END{
# to ensure constant order
cols = asorti(head)
for(i=1;i<=cols;i++)
header = header "|" head[i]
print substr(header, 2)
for(r=1; r<=rows; r++){
row = ""
for(c=1; c<=cols; c++)
row = row "|" LOCUS[head[c],r]
print substr(row, 2)
}
}
指南 注意:我抓到的gbff每个文件都有多个GenBank记录
ls -l
-rw-r--r-- 1 tomc tomc 1724943 Mar 31 23:21 bacteria.24.genomic.gbff
-rw-r--r-- 1 tomc tomc 3216313 Mar 31 23:53 bacteria.431.genomic.gbff
-rwxr-xr-x 1 tomc tomc 487 Mar 31 23:51 locus_trna_transpose.awk
结果: 注意:使用管道作为字段分隔符以便于查看
./locus_trna_transpose.awk bacteria*.gbff
NZ_AWIQ01000161|NZ_AWIQ01000167|NZ_AWIQ01000183|NZ_AWKN01000226|NZ_AWKN01000319|NZ_AWLJ01000031|NZ_AWLJ01000043|NZ_AWLJ01000050|NZ_JORA01000025|NZ_JORA01000026|NZ_JORA01000030|NZ_JORA01000031|NZ_JORA01000032|NZ_JORA01000034|NZ_JORA01000036|NZ_JORA01000037
tRNA-binding|tRNA-Arg|tRNA-Met|tRNA-Asn|tRNA-binding|tRNA-Val|tRNA-Leu|tRNA-binding|tRNA-Pro|tRNA-Val|tRNA-Arg|tRNA-Arg|tRNA-Met|tRNA-Phe|tRNA-Met|tRNA-Met
|||||tRNA-Val|||tRNA-Arg|tRNA-Val|tRNA-Arg|tRNA-Arg|tRNA-Met||tRNA-binding|tRNA-Leu
||||||||tRNA-Ala|tRNA-Val||tRNA-Ser|tRNA-Met|||
||||||||tRNA-Ala|tRNA-Val|||tRNA-Gly|||
||||||||tRNA-Ala|tRNA-Lys|||tRNA-modifying|||
||||||||tRNA-Ala|||||||
对于那些一起玩的人来说, 这些输入文件从
中抓取得很小答案 3 :(得分:1)
此类处理实际上超出了grep
的功能。你最好创建一个完全符合你想要的小型自定义脚本。我会使用python
和pandas
来完成任务。这是一个实现,基于我目前对您的描述的理解。
import re
import sys
import pandas as pd
# Regular expressions; adjust as necessary
regex_locus = re.compile('LOCUS\s+(\S+)')
regex_trna = re.compile('"(tRNA-.*)"')
# Aggregate results in a dataframe
df = pd.DataFrame()
total_files = len(sys.argv[1:])
# Iterate over the files given on the command line
for index, file in enumerate(sys.argv[1:]):
print("Processing {:4d}/{:4d}: {}".format(index + 1, total_files, file))
# Per file variables.
locus = None
trna = []
# Open the file for reading
with open(file) as fd:
# Find LOCUS value
for line in fd:
match = regex_locus.search(line)
if match:
locus = match.group(1)
# Done with this section
break
# Find tRNA values
for line in fd:
match = regex_trna.search(line)
if match:
trna.append(match.group(1))
# Done with this file
if locus is not None:
# Add the entry for this file. Convert the list to a pandas Series to account for differing lengths.
df[locus] = pd.Series(trna)
# Write out the final DataFrame as csv
df.to_csv('output.csv', index=False)
# And as text...
with open('output.txt', 'w') as fd:
df.to_string(fd, index=False)
output.csv
和output.txt
。输出格式基本上是免费的,因为数据在DataFrame中。build_table.py
,则会将其调用为:python build_table.py *.gbff