我正在尝试解析多个文件以提取特定行并将它们输出到另一个文件中。但是,这些信息在我的文件中的位置可以根据特定参数进行更改。
为此,我想使用if 语句。在大多数情况下,我需要提取的内容位于第 6 行和第 7 行:
# IGBLASTN 2.5.1+
# Query: RL0575_B2_no210_RL0575_B2_ACPA_positive_LC
# Database: human_gl_V human_gl_D human_gl_J BCR_C_all.fa
# Domain classification requested: imgt
# V-(D)-J rearrangement summary for query sequence (Top V gene match, Top J gene match, Chain type, stop codon, V-J frame, Productive, Strand). Multiple equivalent top matches having the same score and percent identity, if present, are$
IGLV4-69*01 IGLJ1*01 VL No In-frame Yes +
为此我这样做:
a=`ls *LC.fa | awk -F "." '{print $1}'`; #here i just strip the name of the files for the loop
for i in $a;
do cat $i.fmt7 | awk 'NR==6, NR==7' > $i.parsed.txt;
done
然而,在某些情况下,文件的第 8 行和第 9 行包含该信息,因为第 6 行有附加注释:
# IGBLASTN 2.5.1+
# Query: RL0624_B10_no15_RL0624_B10_ACPA_positive_LC
# Database: human_gl_V human_gl_D human_gl_J BCR_C_all.fa
# Domain classification requested: imgt
# Note that your query represents the minus strand of a V gene and has been converted to the plus strand. The sequence positions refer to the converted sequence.
# V-(D)-J rearrangement summary for query sequence (Top V gene match, Top J gene match, Chain type, stop codon, V-J frame, Productive, Strand). Multiple equivalent top matches having the same score and percent identity, if present, are$
IGKV3-20*01 IGKJ2*01 VK Yes In-frame No -
我想以与上面类似的方式进行,但是
a=`ls *LC.fa | awk -F "." '{print $1}'`; #here i just strip the name of the files for the loop
for i in $a;
if [my condition?] # <== here I do not know how to formulate the condition!
then
cat $i.fmt7 | awk 'NR==8, NR==9'
else
cat $i.fmt7 | awk 'NR==6, NR==7' > $i.parsed.txt;
fi
done
尽管前导码长度不同,如何确保提取正确的行?请注意,这些文件包含的数据行比此处显示的要多,因此我需要提取的不仅仅是最后两行。
任何想法都非常感激。
答案1
您的文件似乎包含一个相关数据行,其余部分要么是空的,要么是以#
;开头的注释行。然而最后一个是您想要保留的标头。您的问题似乎是注释行数不同。
如果任务实际上是提取标题和这一数据行以输出到“已解析的”摘要文件中,您可以指示awk
忽略所有空行或以字符开头的行#
,而不是由起始模式标识的标题# V-(D)-J
,如:
awk '$0~/^# V-\(D\)-J/ || ($0!~/^#/ && NF>0) {print}' input_file > parsed_file
另一方面,如果您的文件包含多个数据行,并且您只想打印标题和第一个数据行,则命令awk
必须如下所示:
awk '$0~/^# V-\(D\)-J/ {print} ($0!~/^#/ && NF>0) {print;exit}' input_file > parsed_file
要在 shell 循环中执行此操作,您可以这样做
for file in *LC.fa
do
infile="${file%.*}.fmt7"
outfile="${file%.*}.parsed.txt"
awk '$0~/^# V-\(D\)-J/ || ($0!~/^#/ && NF>0) {print}' "$infile" > "$outfile"
done
或者
for file in *LC.fa
do
infile="${file%.*}.fmt7"
outfile="${file%.*}.parsed.txt"
awk '$0~/^# V-\(D\)-J/ {print} ($0!~/^#/ && NF>0) {print;exit}' "$infile" > "$outfile"
done
分别。
随着 的输出的解析ls
,该循环更加稳健,即强烈不推荐。
awk
对命令的一些解释
awk
适用于“条件规则”语法,其中条件位于“主”程序空间中,相应的规则位于{ ... }
.
在第一个例子中,我们有一个条件和一个规则:
- 如果该行(由 取消引用
$0
)与正则表达式匹配^# V-\(D\)-J
,即^
以字符串 ( )开头V-(D)-J
- 或者(
||
) 确实如此不是#
以a ($0!~/^#/
表达式)开头和另外是非空的,即它至少有一个由“字段分隔符”变量定义的字段(NF>0
- 我们也可以将其缩写为简单)(默认为空格)NF
然后是print
线。
这将打印标题和任何连续的数据行。
在第二个例子中,我们有两个具有关联规则的条件:
- 如果该行以字符串 开头
# V-(D)-J
,print
则该行。 - 如果该行不是以 开始
#
,且 不为空,print
然后立即exit
,即终止awk
文件的处理。
这样,“标题”就会被打印出来,但是一旦遇到并打印第一个“数据”行,我们就会停止执行,然后只打印标题以及每个文件的第一个数据行。
答案2
您可以设置一个 for 循环并调用 sed 来生成解析文件。
for f in *LC.fa; do
if=${f%.*}.fmt
of=${f%.*}.parsed.txt
sed -e '
8N;9q
6N;/\n./q;d
' < "$if" > "$of"
done