/ / Comment utiliser sed pour effectuer des milliers de substitutions dans un fichier à l'aide d'un fichier de référence? - base de données, bash, dictionnaire, awk, sed

Comment puis-je utiliser sed pour effectuer des milliers de substitutions dans un fichier en utilisant un fichier de référence? - base de données, bash, dictionnaire, awk, sed

J'ai un gros fichier avec deux colonnes comme ceci:

 tiago@tiago:~/$ head Ids.txt
TRINITY_DN126999_c0_g1_i1 ENSMUST00000040656.6
TRINITY_DN126999_c0_g1_i1 ENSMUST00000040656.6
TRINITY_DN126906_c0_g1_i1 ENSMUST00000126770.1
TRINITY_DN126907_c0_g1_i1 ENSMUST00000192613.1
TRINITY_DN126988_c0_g1_i1 ENSMUST00000032372.6
.....

et j'ai un autre fichier avec des données, comme ceci:

"baseMean" "log2FoldChange" "lfcSE" "stat" "pvalue" "padj" "super" "sub" "threshold"
"TRINITY_DN41319_c0_g1" 178.721774751278 2.1974294626636 0.342621318593487 6.41358066008381 1.4214085388179e-10 5.54686423073089e-08 TRUE FALSE "TRUE"
"TRINITY_DN87368_c0_g1" 4172.76139849472 2.45766387851112 0.404014016558211 6.08311538160958 1.17869459181235e-09 4.02673069375893e-07 TRUE FALSE "TRUE"
"TRINITY_DN34622_c0_g1" 39.1949851245197 3.28758092748061 0.54255370348027 6.05945716781964 1.3658169042862e-09 4.62597265729593e-07 TRUE FALSE "TRUE"
.....

Je pensais utiliser sed pour effectuer une traduction des valeurs dans la première colonne du fichier de données, en utilisant le premier fichier comme dictionnaire.

Autrement dit, compte tenu de chaque ligne du fichier de donnéesà son tour, si la valeur de la première colonne correspond à une valeur de la première colonne du fichier de dictionnaire, une substitution sera effectuée; sinon, la ligne serait simplement imprimée.

Toute suggestion serait appréciée.

Réponses:

1 pour la réponse № 1

Vous pouvez transformer votre premier fichier Ids.txt dans un script sed:

$ sed -r "s| *(S+) (S+)|s/^"1/"2/|" Ids.txt > repl.sed
$ cat repl.sed
s/^"TRINITY_DN126999_c0_g1_i1/"ENSMUST00000040656.6/
s/^"TRINITY_DN126999_c0_g1_i1/"ENSMUST00000040656.6/
s/^"TRINITY_DN126906_c0_g1_i1/"ENSMUST00000126770.1/
s/^"TRINITY_DN126907_c0_g1_i1/"ENSMUST00000192613.1/
s/^"TRINITY_DN126988_c0_g1_i1/"ENSMUST00000032372.6/

Cela supprime les espaces de début et transforme chaque ligne en une commande de substitution.

Ensuite, vous pouvez utiliser ce script pour effectuer les remplacements dans votre fichier de données:

sed -f repl.sed datafile

... avec redirection vers un autre fichier, ou en place avec sed -i.

Si vous n'avez pas GNU sed, vous pouvez utiliser cette version conforme POSIX de la première commande:

sed "s| *([^ ]*) ([^ ]*)|s/^"1/"2/|" Ids.txt

Cela utilise des expressions régulières de base au lieu d'étendues et utilise [^ ] pour "pas d'espace" au lieu de S.


1 pour la réponse № 2

Étant donné que le premier fichier (le fichier de dictionnaire) est volumineux, sed peut être très lent; une approche beaucoup plus rapide et pas beaucoup plus complexe serait d'utiliser awk comme suit:

awk -v col=1 -v dict=Ids.txt "
BEGIN {while(getline<dict){a["""$1"""]="""$2"""} }
$col in a {$col=a[$col]}; {print}"

(Ici, "Ids.txt" est le fichier de dictionnaire et "col" est le numéro de colonne du champ d'intérêt dans le fichier de données.)

Cette approche présente également l'avantage de ne nécessiter aucune modification du fichier dictionnaire.


0 pour la réponse № 3
#!/bin/bash

# Declare hash table
declare -A Ids

# Go though first input file and add key-value pairs to hash table
while read Id; do
key=$(echo $Id | cut -d " " -f1)
value=$(echo $Id | cut -d " " -f2)
Ids+=([$key]=$value)
done < $1

# Go through second input file and replace every first column with
# the corresponding value in the hash table if it exists
while read line; do
first_col=$(echo $line | cut -d """ -f2)
new_id=${Ids[$first_col]}

if [ -n "$new_id" ]; then
sed -i s/$first_col/$new_id/g $2
fi
done < $2

J'appellerais le script comme

./script.sh Ids.txt data.txt