awk 的 'pattern { action }' 模型
awk 把每一行(record)依分隔符切成欄位 $1, $2, $3 ...($0 是整行)。語法:
awk 'PATTERN { ACTION }' file
對於符合 PATTERN 的每一行,執行 ACTION。BEGIN{} 在處理任何行前執行;END{} 在所有行處理完後執行。NR = 目前行號,NF = 目前行的欄位數。
awk splits each line (record) into fields $1, $2, $3 … ($0 is the whole line). The grammar:
awk 'PATTERN { ACTION }' file
For each line matching PATTERN, run ACTION. BEGIN{} runs before all input; END{} after all lines. NR = current line number, NF = number of fields on the current line.
awk — 生資最常用的範例
awk 的 5 個生資神技
# 1. 計算 FASTQ 中的總 reads 數 + 平均長度 # Count reads + average length zcat sample.fastq.gz | awk 'NR%4==2 {n++; s+=length($0)} END{printf "%d reads, avg %.1f bp\n", n, s/n}'
# 2. 從 GTF 提取所有 protein-coding transcripts 的 BED # Extract protein_coding transcript intervals as BED awk '$3=="transcript" && /protein_coding/ {print $1"\t"$4-1"\t"$5"\t"$10"\t.\t"$7}' genes.gtf \ | tr -d '";' > protein_coding.bed
# 3. BED 0-based vs 1-based 轉換(1-based half-open → 0-based half-open 形式) # Convert 1-based to 0-based BED start awk -F'\t' 'BEGIN{OFS="\t"} {$2=$2-1; print}' in.bed > out.bed # 統計 BED 各 chrom 上的 interval 數 awk '{a[$1]++} END{for(c in a) print c, a[c]}' regions.bed
# 4. VCF 中 PASS 且 QUAL > 30 的變異 # PASS variants with QUAL > 30 in a VCF awk -F'\t' '/^#/{print; next} $7=="PASS" && $6>30' cohort.vcf > highq.vcf
# 5. 每個 sample 的 read 計數(樣本表 + 計數表 join 不夠時) # Per-sample read count from a counts file awk -F'\t' 'NR>1 {sums[$1]+=$3} END{for(s in sums) print s, sums[s]}' counts.tsv
sed — 批次取代與簡單編輯
陷阱:macOS 上 sed -i 必須加空字串 sed -i '',Linux 不需要。寫跨平台 script 時可改用 sed -i.bak(兩邊都認)。
Gotcha: on macOS sed -i needs an empty string sed -i ''; Linux doesn't. For portable scripts use sed -i.bak (works on both).
awk vs sed vs grep — 該選哪一個?
| 工具 | 擅長 | 簡單口訣 |
|---|---|---|
| grep | 搜尋/篩選整行 | 找符合條件的「行」 |
| cut | 抽出固定欄位(tab 分隔) | 切「欄」 |
| sed | 批次取代、刪行、行範圍 | 改寫整段文字 |
| awk | 欄位 + 條件 + 運算 + 統計 | 當 grep + cut 不夠用時 |
互動:在 mini GTF 上練習 awk + sed
建議試試:awk '$3=="exon"' genes.gtf、awk '$3=="gene" {print $1, $4, $5}' genes.gtf、sed 's/chr//' regions.bed、awk -F'\t' '{print $1}' samples.tsv | sort -u
Try: awk '$3=="exon"' genes.gtf, awk '$3=="gene" {print $1, $4, $5}' genes.gtf, sed 's/chr//' regions.bed, awk -F'\t' '{print $1}' samples.tsv | sort -u
📝 自我檢測
1. awk '$3=="exon"' genes.gtf 在做什麼?
1. What does awk '$3=="exon"' genes.gtf do?
2. 想計算 FASTQ 中每個序列的長度,要選哪一個?
2. Which awk picks only the FASTQ sequence lines and prints their length?
3. sed 's/chr//' regions.bed 的效果?
3. Effect of sed 's/chr//' regions.bed?
4. 關於 sed -i,下列何者最正確?
4. Which is most accurate about sed -i?