How to use awk with multiple files?
file1.txt:
John John2
Apple Apple2
Mike Mike2
Max Max2
file2.txt:
Max
Tim
Tom
Poole
Mike
1. Find identifiers that occur in both files
Code:
awk -F "\t" ' NR==FNR { array[$1]; next} $0 in array {print}' file1.txt file2.txt
The two files are processed sequentially. NR == FNR identifies records from the first non-empty file, allowing its identifiers to populate a lookup table.
NR counts records across both files; FNR restarts in each file. For two four-line files, both counters run from 1 to 4 in the first file. In the second, NR runs from 5 to 8 while FNR runs from 1 to 4.
For this example, NR == FNR holds only while reading the first file.
{ array[$1]; next } stores each first-column identifier as a key. next skips the remaining actions for that record.
When reading the second file, $0 in array {print} tests whether the whole line matches a stored key and prints matching records.
Max
Mike
2. Replace identifiers in the second file using a mapping from the first
For example, the mapping replaces Mike in file2 with Mike2.
Code:
awk -F "\t" ' NR==FNR { array[$1] = $2; next } $0 in array {$0 = array[$0]} {print} ' file1.txt file2.txt
array[$1] = $2 builds a key–value mapping from the first file. When reading the second file, a matching key is replaced by its mapped value.
Label the duplicate headers in a fasta file
Suppose a FASTA contains duplicate gene identifiers that should receive distinct suffixes. Transform:
>apple
ATGCATGC
>apple
ATCGATCG
into:
>apple.1
ATGCATGC
>apple.2
ATCGATCG
→ Code:
awk '{ if (NR==FNR) {
if (/^>/){s[$0]++}
next;}
if (/^>/){k[$0]++;
if (s[$0]>1) { $0=$0"_"k[$0] }
}
print
}'
input.fa input.fa > output.fa
# OR a easier way
awk '/^>/ {if (seen[$0]++){$0=$0"_"seen[$0]} } {print}' input.fa > output.fa
s[$0]++counts the number of times that specific header line appears in the file. For example, given this FASTA:
>header1
>header2
>header1
>header3
>header2
The s array will contain:
s[">header1"] = 2
s[">header2"] = 2
s[">header3"] = 1
Result:
>header1_1
>header2_1
>header1_2
>header3_1
>header2_2
if (s[$0]>1) { $0=$0"_"k[$0] }: if a header occurs more than once, append its occurrence number to distinguish the repeated entries.
Naming caveat: if the input already contains suffixes such as xxx_1, choose a different convention before using this code.
Conditional expressions in awk
awk -F ' ' 'NR==FNR{ map[">"$1] = ">"$2; next;} {if (/^>/) {$0=(map[$0]) ? map[$0] : $0} print} ' Hofstenia_miamia/processed/Hof_pep.vs.nucl_output_1.11 \
Hofstenia_miamia/processed/Hof_output_1.2.faa > Hofstenia_miamia/processed/Hof_output_1.12.faa
The ternary conditional expression is:
(condition) ? (expression_if_true) : (expression_if_false)
Filter rows by a pattern in a particular column
awk -F"\t" '$2 !~ /^g[0-9].*|Hof/' mmseqs2_RBH/Prae_Hof_RBH_pep.result.sort > mmseqs2_RBH/Prae_Hof_RBH_pep.result.sort.deHofPepID
sed in awk
Apply a substitution to a particular field rather than the entire line.
awk -F"," '{gsub("-","_",$7)}1' OFS="," celltype_markers_Hulett.csv
excape single quote in awk
lvl1 KC-a'/b' vsRest WholeBrain Up chr3L:21863491-21864316 "" 3.9e-250 4.2e-245 0.84 1 0.51 0.49 KC-a'/b'--lvl1_vsRest_wWB
lvl1 KC-a'/b' vsRest WholeBrain Up chrX:14125993-14126604 "" 6.9e-271 7.4e-266 0.79 1 0.5 0.5 KC-a'/b'--lvl1_vsRest_wWB
To select records whose second column is KC-a'/b':
awk '$2 == "KC-a'\''/b'\''"'
The example below shows how shell quoting and escaped quote characters interact when a literal apostrophe appears in the awk pattern.