Bash

提取文件內不同位置的行

  • June 9, 2020

我正在嘗試解析幾個文件以提取特定行並將它們輸出到另一個文件中。但是,這些資訊在我的文件中的位置可以根據特定參數進行更改。

為此,我正在考慮使用if-statement。在大多數情況下,我需要提取的內容位於第 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

儘管序言的長度不同,我如何確保提取正確的行?請注意,這些文件包含的數據行比此處顯示的要多,因此我需要提取的不僅僅是最後兩行。

任何想法都非常感謝。

您的文件似乎包含一個相關的數據行,其餘的要麼是空的,要麼是一個以#;開頭的註釋行。但是最後一個是您要保留的標題。您的問題似乎是註釋行的數量有所不同。

如果任務實際上是提取標題和這一數據行以輸出到“已解析”摘要文件中,您可以指示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
  • ( ||) 它不( 表達式 ) 開頭,#而且$0!~/^#/不是的,即它至少有一個欄位 ( NF>0- 我們也可以將其縮寫為簡單NF) 由“欄位分隔符”變數定義(預設值到空格)

然後print行。

這將列印標題和任何連續的數據行。

在第二個範例中,我們有兩個帶有關聯規則的條件:

  • 如果該行以 string 開頭,則# V-(D)-Jprint行。
  • 如果該行不開頭#,並且不為空,print則該行然後立即exit,即終止awk文件的處理。

這樣,“標題”被列印出來,但是一旦遇到並列印了第一個“數據”行,我們就停止執行,然後只列印標題和每個文件的第一個數據行。

引用自:https://unix.stackexchange.com/questions/591765