使用映射文件替换文件中的多个字符串
Posted
技术标签:
【中文标题】使用映射文件替换文件中的多个字符串【英文标题】:Replace multiple strings in file using a mapping file 【发布时间】:2014-06-07 21:00:32 【问题描述】:如何使用映射文件(+ 50K 行)替换一个大文件(+ 500K 行)中的多个字符串?映射文件的结构如下:
A1 B1
A2 B2
A3 B3
.. ..
大文件的结构是这样的:
A1 A2
A1 A3
A1 A8
A2 A1
A2 A3
A3 A10
A3 A13
并且大文件中的每个字符串都必须使用映射文件进行替换。
想要的结果:
B1 B2
B1 B3
B1 B8
B2 B1
B2 B3
B3 B10
B3 B13
我尝试在映射文件的每一行上都使用 awk,但这需要很长时间……这是 awk 命令。所以我为映射文件的每一行编写了一个循环启动一个 awk 命令,我将结果保存在一个临时文件中,并将这个结果用于映射文件的下一行的新 awk(我知道效率不是很高..)
cat inputBigFile.txt | awk ' gsub( "A1","B1" );1' > out.txt
提前致谢
【问题讨论】:
究竟是什么awk
命令你试过太慢了?
搜索答案解释如何使用NR==FNR
的众多近似重复项之一。
无论如何,您不应该将cat
数据发送到可以自行读取数据的程序中,例如awk
。 awk ' gsub( "A1","B1" );1' inputBigFile.txt > out.txt
。要查看程序使用了多长时间,请以 time
eks: time awk 'code
file > out` 开始它。
【参考方案1】:
$ awk 'NR==FNRmap[$1]=$2;next if($1 in map)$1=map[$1]; if($2 in map)$2=map[$2]1' mappings file
B1
B1
B1 A8
B2
B2
B3 A10
B3 A13
我假设专门检查和替换两列比循环 NF
和/或使用 gsub
更快。
编辑:重要的是:
$ wc -l file
8388608 file
.
$ time awk 'NR==FNRmap[$1]=$2;next if($1 in map)$1=map[$1]; if ($2 in map)$2=map[$2]1' mappings file >/dev/null
real 0m6.941s
user 0m6.904s
sys 0m0.016s
.
$ time awk 'NR==FNRmap[$1]=$2;next for(i=1;i<=NF;i++)$i=($i in map)?map[$i]:$i1' mappings file >/dev/null
real 0m10.311s
user 0m10.249s
sys 0m0.036s
.
$ awk --version | head -n 1
GNU Awk 3.1.8
【讨论】:
谢谢,太好了。但是您在 awk 命令中忘记了 $(在 $2=map[2] 中): awk 'NR==FNRmap[$1]=$2;next if($1 in map)$1=map[$1]; if($2 in map)$2=map[$2]1' 映射文件 一件事:如何强制以制表符分隔输出? @NicoBxl 使用awk -v OFS='\t' [...]
设置输出分隔符。但是,这只会影响至少其中一列已更改的行。要强制,您可以在if
之后添加显式print $1, $2
(并删除尾随1
),例如[...]; if($2 in map)$2=map[$2]; print $1, $2
.以上是关于使用映射文件替换文件中的多个字符串的主要内容,如果未能解决你的问题,请参考以下文章