次のタブ区切り文字を含むファイルがあります。
Chr1 mak gene 120221 120946 . + . ID=spa-h0003.02;Name=spa-h0003.02
Chr1 mak mRNA 120221 120946 . + . ID=spa-cap_Chr1_00M;Parent=spa-h0003.02;Name=spa-cap_Chr1_00M
Chr1 mak exon 120221 120946 . + . Parent=spa-cap_Chr1_00M
Chr1 mak gene 18546165 18546939 . + . ID=spa-h0004.02;Name=spa-h0004.02
Chr1 mak mRNA 18546165 18546939 . + . ID=spa-cap_Chr1_18;Parent=spa-h0004.02;Name=spa-cap_Chr1_18
Chr1 mak exon 18546165 18546504 . + . Parent=spa-cap_Chr1_18
Chr1 mak exon 18546791 18546939 . + . Parent=spa-cap_Chr1_18
3番目の列に「gene」がある場合にのみ別の文字列を置き換えたいと思います。ただし、9番目の列の文字列は、2番目のファイルの情報に基づいて次のように置き換える必要があります(タブを含む)。
spa-h0003.02 spa-cap_Chr1_00M
spa-h0004.02 spa-cap_Chr1_18
私は何をすべきかわかりません。私は次のように考えています。 (XXは2番目のファイルの情報であるべきですか?)
cat file | awk '$3 == "gene" && $9 == "spa-" {$9 = "XX"} {print}'
しかし、2番目のファイルの情報をどのように使用しますか?おそらく:
while read n k; do sed -i 's/$n/$k/g' file1; done < fileA
答え1
file1
置換したいテキストがあり、file2
代替テキストがあり、それらID=
の間で検索を実行できると仮定すると、次のawkスクリプトを使用できます(より人気があるようです)。
awk -F'\t' '
NR==FNR{
a[$1]=$2 # fills the array a with the replacement text
next
}
$3=="gene"{ # check only lines with 'gene'
id=gensub("ID=([^;]*);.*","\\1",1,$9); # extract the id string
if(id in a) # if the id is part of the array a
gsub(id,a[id]) # replace it
}
1 # print the line
' file2 file1
答え2
人気のない選択:Tcl。 Tclにはstring map
これを行う素晴らしいコマンドがあります。正確にこれ。残念ながら、Tclは実際にはPerlスタイルのシングルライナー用に作られていません。
echo '
# read the mapping file into a list
set fh [open "mapping" r]
set content [read $fh]
close $fh
set mapping [regexp -all -inline {\S+} $content]
# read the contents of the data file
# and apply mapping to field 9 when field 3 is "gene"
set fh [open "file" r]
while {[gets $fh line] != -1} {
set fields [split $line \t]
if {[lindex $fields 2] eq "gene"} {
lset fields 8 [string map $mapping [lindex $fields 8]]
}
puts [join $fields \t]
}
close $fh
' | tclsh
awkを使って次のように書く。
awk -F'\t' -v OFS='\t' '
NR == FNR {repl[$1]= $2; next}
$3 == "gene" {
for (seek in repl)
while ((idx = index($9, seek)) > 0)
$9 = substr($9, 1, idx-1) repl[seek] substr($9, idx + length(seek))
}
{print}
' mapping file