Database 如何使用sed在使用引用文件的文件中进行数千次替换?
我有一个大文件,有两列,如下所示:Database 如何使用sed在使用引用文件的文件中进行数千次替换?,database,bash,dictionary,awk,sed,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_
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"
.....
我还有另一个包含数据的文件,如下所示:
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来翻译数据文件第一列中的值,将第一个文件用作字典
也就是说,依次考虑数据文件的每一行,如果第一列中的值与字典文件的第一列中的值匹配,则将进行替换;否则,该行将被简单地打印出来
任何建议都将不胜感激。您可以将第一个文件
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,可以使用符合POSIX的第一个命令版本:
sed 's| *\([^ ]*\) \([^ ]*\)|s/^"\1/"\2/|' Ids.txt
这使用基本而不是扩展正则表达式,并使用[^]
表示“非空格”,而不是\S
,因为第一个文件(字典文件)很大,所以使用sed
可能非常慢;一种更快且不太复杂的方法是使用awk
,如下所示:
#!/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
awk -v col=1 -v dict=Ids.txt '
BEGIN {while(getline<dict){a["\""$1"\""]="\""$2"\""} }
$col in a {$col=a[$col]}; {print}'
awk-v col=1-v dict=Ids.txt'
BEGIN{while(GetLine)如果数据文件包含Ids.txt中不存在的密钥怎么办?根据问题描述,它应该保持不变。如果repl.sed中的行如下所示,则效率更高,可能更安全:s/^“…/”…使用parallel运行所有6个文件需要15分钟才能完成对每行输入运行一次cut
和两次sed
与运行两次sed
相比,速度会非常慢,一次创建sed
脚本,然后一次运行sed
脚本。如果只有两个li如果要更改,这没什么大不了的,但是有成千上万个。好吧,这取决于sed脚本是否能够一次编辑文件,我不认为是这样(?)。如果每行s/xxx/yyy/
都会导致sed
遍历数据文件,那么每个id只需一次。我编辑了我的代码,在获取第一列时删除了一个不必要的sed
,但当然它仍然会在每次迭代中执行sed
和cut
一次。sed
是a(the?)“流编辑器”。它将脚本中的操作依次应用于每一行输入。它可以处理任意大的数据文件;sed
的旧版本可能会遇到足够大的sed
脚本的问题,但大多数现代版本的sed
已经失去了旧版本的限制。好的,我做了计算。给定n=(数据文件中的行),m=(ID文件中的行),sed脚本逐行遍历数据文件,每个s/xxx/yyy/
应用一次,因此复杂度为n×m。我的脚本遍历数据文件一次,但对数据文件再次进行替换,因此复杂度为n×n。给定n>>m,我的脚本的计算复杂度较低,但如果≈ n或甚至m>n如果cut
需要很长时间,那么我的脚本应该会慢一些。在每次迭代中重新启动sed
都会受到一些惩罚。我认为真正的惩罚是Bash循环速度太慢。事实上,它比sed快得多。@TiagoBruno-你能更具体一点吗?实际上,这会很有趣g(可能对某些人有用)为(a)awk解决方案;(b)发布的sed解决方案;(c)修改后的sed解决方案使用s/^../…/
而不仅仅是s/”…/…/
。我将很快在这里发布每个解决方案所用的时间。在一些虚拟文件上进行的测试表明,awk的加速系数为2-3,但正如您所说,使用大型字典文件,这可能会更大。期待对真实数据的测量!