如何使用sed使用参考文件在文件中进行数千次替换?

时间:2016-02-05 03:19:28

标签: database bash dictionary awk sed

我有一个包含两列的大文件:

 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
 .....

我有另一个包含数据的文件,如下所示:

"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"
.....

我正在考虑使用sed在数据文件的第一列中执行值的转换,使用第一个文件作为字典。

也就是说,依次考虑数据文件的每一行,如果第一列中的值与字典文件的第一列中的值匹配,则将进行替换;否则,该行就会被打印出来。

任何建议都将不胜感激。

3 个答案:

答案 0 :(得分:1)

您可以将第一个文件Ids.txt转换为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/

这将删除前导空格并使每一行成为替换命令。

然后,您可以使用此脚本在数据文件中执行替换:

sed -f repl.sed datafile

...重定向到另一个文件,或与sed -i一起就地。

如果您没有GNU sed,可以使用第一个命令的POSIX符合版本:

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

这使用基本而非扩展的正则表达式,并使用[^ ]代替\S而不是def word_len_dict(text): the_dict = {} user_input = str(text) words_list = user_input.split() for word in words_list: if len(word) in the_dict: the_dict[len(word)] += [word] else: the_dict[len(word)] = [word] return the_dict

答案 1 :(得分:1)

由于第一个文件(字典文件)很大,使用sed可能会非常慢;更快,更复杂的方法是使用awk,如下所示:

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

(此处,“Ids.txt”是字典文件,“col”是数据文件中感兴趣字段的列号。)

此方法还具有不需要对字典文件进行任何修改的优点。

答案 2 :(得分:0)

#!/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

我会将脚本称为

./script.sh Ids.txt data.txt