![使用 grep 将与模式匹配的第一行中的所有行返回到不同的模式](https://linux22.com/image/157499/%E4%BD%BF%E7%94%A8%20grep%20%E5%B0%86%E4%B8%8E%E6%A8%A1%E5%BC%8F%E5%8C%B9%E9%85%8D%E7%9A%84%E7%AC%AC%E4%B8%80%E8%A1%8C%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E8%A1%8C%E8%BF%94%E5%9B%9E%E5%88%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E6%A8%A1%E5%BC%8F.png)
我相信我需要使用 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
。
它用-e
在echo
哪些需要的地方bash
。
像./script_name
或一样运行它bash script_name
。