使用 grep 将与模式匹配的第一行中的所有行返回到不同的模式

使用 grep 将与模式匹配的第一行中的所有行返回到不同的模式

我相信我需要使用 grep 因为我正在搜索多个文件,并且我需要文件名在每行上显示为标题。我正在 macOS 上使用终端。

假设我在目录“dir”中有一个文件 file1,其内容如下:

>species one; trnF(ggc)
GGCCC
AACGC
>species one; rrnS
TAGCA
GGCAC

目录“dir”中还有一个附加文件 file2,其内容如下

>species two; trnF(gga)
GGACG
CGACG
GCAC
>species two; rrnS
GCATG
GGCAG

我想得到以下输出:

dir/file1:>species one; trnF(ggc)
dir/file1-GGCCC
dir/file1-AACGC
--
dir/file2:>species two; trnF(gga)
dir/file2-GGACG
dir/file2-CGACG
dir/file2-GCAC

我可以使用 -A 在具有模式的行之后获取特定的指定行数:

$ grep -A 2 'trnF' dir/file*

但这些文件在 grep 命令之后有不同的行数,所以我得到以下内容:

dir/file1:>species one; trnF(ggc)
dir/file1-GGCCC
dir/file1-AACGC
--
dir/file2:>species two; trnF(gga)
dir/file2-GGACG
dir/file2-CGACG

我怎样才能获得直到下一个“>”符号的所有内容?

答案1

正如您所发现的,grep -A它不灵活,因为它只允许指定静态的上下文行数。

相反,这里有一个awk命令,用于检测所选序列何时发生,并将其输出,直到遇到另一个与条件不匹配的序列头:

awk -v name='trnF' -v OFS=':\t' '
    FNR == 1 && NR > 1 { print "--" }
    /^>/ { out=0 }
    $0 ~ "^>.*" name { out=1 }
    out == 1 { print FILENAME, $0 }' files

-v name=something选项将分配something给代码name中的变量awk,并将用作与包含给定字符串的 fasta 标题行匹配的正则表达式的一部分。

最后一段的输出awk可能类似于

file:   >species one; trnF(ggc)
file:   GGCCC
file:   AACGC
--
file1:  >species one; trnF(ggc)
file1:  GGCCC
file1:  AACGC
--

:后面的制表符用作文件名和数据之间的分隔符,可以通过OFS在命令行上设置为其他内容来更改-v OFS=somethingelse

答案2

#! /bin/bash

for i in dir/file*
do
    [ -n "$is_first_file" ] && echo
    awk -v filename="$i" 'BEGIN { temp=1 }  { if ($1 ~ /^>/ && temp == 0){exit} } {if ( $1 ~ /^>/ && temp == 1 ) {print filename,"\b:","\b"$0,temp=0 } else { print filename,"\b-","\b"$0 }}' "$i"
    echo -n '--'
    is_first_file=no
done
echo -n -e "\b\b"

没有太多经验awk,但我想这应该会给你你想要的确切输出。

也是我经常犯的一个错误。不要像 那样运行这个脚本sh script_name

它用-eecho哪些需要的地方bash

./script_name或一样运行它bash script_name

相关内容