Awk Grep多个文件并将输出保存到不同的列

Awk Grep多个文件并将输出保存到不同的列,awk,command-line,grep,Awk,Command Line,Grep,使用mac命令行,我想grep多个文件并将输出保存到不同的列 以下是我的一个文件ncbi.nlm.nih.gov/nuccore/NZ_AP013294的示例(单击“发送到”,“文件”将格式另存为“完整genbank文件”)。我有大约2000个这样的。我只想知道基因座(每个文件都有一个基因座,并且总是有一个基因座),然后每次它有tRNA-时,例如tRNA-Glu(tRNA-出现在整个文档中,可能有0到200个基因座) 当我在其中一个文件上执行此操作时,此操作有效: grep -e "LOCUS-

使用mac命令行,我想grep多个文件并将输出保存到不同的列

以下是我的一个文件ncbi.nlm.nih.gov/nuccore/NZ_AP013294的示例(单击“发送到”,“文件”将格式另存为“完整genbank文件”)。我有大约2000个这样的。我只想知道基因座(每个文件都有一个基因座,并且总是有一个基因座),然后每次它有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

。。。等

更新答案

我认为我最初的方法对于您拥有的文件数量来说过于占用资源,因此这里有一个不太占用资源的版本:

#!/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”的文件中,然后使用以下命令使其可执行:

chmod +x $HOME/go
然后,您可以通过执行以下操作在任何目录中运行它:

cd some/place/where/your/files/are
$HOME/go

原始答案

我认为这是你想要的:

parallel 'grep "term" {} > {#}.tmp' ::: *txt ; paste *tmp ; rm *tmp
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
样本输出

term1   term1
term3   term2
        term3
那就是说。。。“在名称以
txt
结尾的所有文件中查找
term
,保存
1.tmp
中第一个文件、
2.tmp
中第二个文件的输出,依此类推。最后,将所有临时文件粘贴在列中并删除。”

您需要知道,使用GNU Parallel时,
{}
表示“当前参数/文件”
{}
表示“当前作业编号”,最后,
::
将参数与要应用的命令分开


您也可以在没有临时文件的情况下执行此操作。在
grep
输出的每一行前面加上GNU Parallel作业编号,然后在Perl中传递批次,去掉作业编号,并用8*那么多的空格替换:

parallel --tag-string {#} 'grep "term" {}' ::: *txt | perl -plne 's/^(\d+)\s*/" " x (8*($1-1))/e'

term1
term3
        term1
        term2
        term3
Perl与所有Mac一起提供

对于任何感兴趣的人来说,这是Lisp装饰类非装饰习语的变体


我使用自制安装GNU Parallel

brew install parallel
(wget -O - pi.dk/3 || curl pi.dk/3/ ) | bash
由于它只是一个Perl脚本,而且所有Mac电脑都配有Perl,因此也可以非常简单地安装它,而无需使用自制

brew install parallel
(wget -O - pi.dk/3 || curl pi.dk/3/ ) | bash

更新的答案

我认为我最初的方法对于您拥有的文件数量来说过于占用资源,因此这里有一个不太占用资源的版本:

#!/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”的文件中,然后使用以下命令使其可执行:

chmod +x $HOME/go
然后,您可以通过执行以下操作在任何目录中运行它:

cd some/place/where/your/files/are
$HOME/go

原始答案

我认为这是你想要的:

parallel 'grep "term" {} > {#}.tmp' ::: *txt ; paste *tmp ; rm *tmp
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
样本输出

term1   term1
term3   term2
        term3
那就是说。。。“在名称以
txt
结尾的所有文件中查找
term
,保存
1.tmp
中第一个文件、
2.tmp
中第二个文件的输出,依此类推。最后,将所有临时文件粘贴在列中并删除。”

您需要知道,使用GNU Parallel时,
{}
表示“当前参数/文件”
{}
表示“当前作业编号”,最后,
::
将参数与要应用的命令分开


您也可以在没有临时文件的情况下执行此操作。在
grep
输出的每一行前面加上GNU Parallel作业编号,然后在Perl中传递批次,去掉作业编号,并用8*那么多的空格替换:

parallel --tag-string {#} 'grep "term" {}' ::: *txt | perl -plne 's/^(\d+)\s*/" " x (8*($1-1))/e'

term1
term3
        term1
        term2
        term3
Perl与所有Mac一起提供

对于任何感兴趣的人来说,这是Lisp装饰类非装饰习语的变体


我使用自制安装GNU Parallel

brew install parallel
(wget -O - pi.dk/3 || curl pi.dk/3/ ) | bash
由于它只是一个Perl脚本,而且所有Mac电脑都配有Perl,因此也可以非常简单地安装它,而无需使用自制

brew install parallel
(wget -O - pi.dk/3 || curl pi.dk/3/ ) | bash

您的问题不清楚,但对您的需求给出一种可能的解释,这可能就是您想要的:

parallel 'grep "term" {} > {#}.tmp' ::: *txt ; paste *tmp ; rm *tmp
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
awk'
/地点/{
轨迹[++numCols]=0美元
}
/tRNA/{
rnas[++rowNrs[numCols],numCols]=$0
numRows=(rowNrs[numCols]>numRows?rowNrs[numCols]:numRows)
}
结束{

对于(colNr=1;colNr您的问题不清楚,但对于您的需求给出了一种可能的解释,这可能就是您想要的:

parallel 'grep "term" {} > {#}.tmp' ::: *txt ; paste *tmp ; rm *tmp
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
awk'
/地点/{
轨迹[++numCols]=0美元
}
/tRNA/{
rnas[++rowNrs[numCols],numCols]=$0
numRows=(rowNrs[numCols]>numRows?rowNrs[numCols]:numRows)
}
结束{

对于(colNr=1;colNr使用awk的模式匹配来找到单个位点和任何tRNA提及

第二项是免费获取轨迹加入,并将awks字段拆分作为第二项

将引用的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)
    }
}
结果: 注意:使用管道作为字段分隔符,以便于查看

./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|||||||
对于那些随波逐流的人, 这些输入文件从中抓取为较小的文件


使用awk的模式匹配来找到单个基因座和任何tRNA提及

第二项是免费获取轨迹加入,并将awks字段拆分作为第二项

分开包装中的tRNA产品(如有)