优化sed以进行多次替换

时间:2016-10-04 17:04:13

标签: bash shell unix sed

我有一个文件users.txt,其中包含

等字样
user1
user2
user3

我想在另一个文件data.txt中找到这些单词并为其添加前缀。 data.txt有近500K行。例如,user1应替换为New_user1,依此类推。我编写了简单的shell脚本,如

for user in `cat users.txt`
do
    sed -i 's/'${user}'/New_&/' data.txt
done

对于大约1000个单词,这个程序需要花费几分钟来处理,这让我感到惊讶,因为sed在找到和替换时非常快。我试图引用Optimize shell script for multiple sed replacements,但仍未发现太多改善。

还有其他方法可以让这个过程更快吗?

3 个答案:

答案 0 :(得分:2)

您可以将users.txt变成这样的sed命令:

$ sed 's|.*|s/&/New_&/|' users.txt 
s/user1/New_user1/
s/user2/New_user2/
s/user3/New_user3/

然后使用它来处理data.txt,或者将上一个命令的输出写入中间文件,或者使用进程替换:

sed -f <(sed 's|.*|s/&/New_&/|' users.txt) data.txt

对于data.txt中的每一行,您的方法都会经历所有users.txt,这会使其变慢。

如果您不能使用流程替换,则可以使用

sed 's|.*|s/&/New_&/|' users.txt | sed -f - data.txt

代替。

答案 1 :(得分:2)

已知Sed非常快(可能只比C差)。

而不是sed 's/X/Y/g' input.txt,请尝试sed '/X/ s/X/Y/g' input.txt。众所周知后者更快。

由于您一次只有#34;一行语义&#34;,您可以使用parallel(在多核cpu-s上)运行它,如下所示:

cat huge-file.txt | parallel --pipe sed -e '/xxx/ s/xxx/yyy/g'

如果您正在处理普通的ascii文件,可以使用&#34; C&#34;来加快速度。区域设置:

LC_ALL=C sed -i -e '/xxx/ s/xxx/yyy/g' huge-file.txt

答案 2 :(得分:1)

或者......一气呵成,我们可以做这样的事情。让我们说,我们有一个500k行的数据文件。

$>    
wc -l data.txt
500001 data.txt

$>    
ls -lrtha data.txt
-rw-rw-r--. 1 gaurav gaurav 16M Oct  5 00:25 data.txt

$>
head -2 data.txt  ; echo ; tail -2 data.txt
0|This is a test file maybe
1|This is a test file maybe

499999|This is a test file maybe
500000|This is a test file maybe

我们假设我们的users.txt在文件“data.txt”中有3-4个关键字,前缀为“ab_”

$>    
cat users.txt
file
maybe
test

因此我们想要阅读users.txt,对于每个单词,我们都希望将该单词更改为新单词。例如,“file”到“ab_file”,“maybe”到“ab_maybe”..

我们可以运行while循环,读取输入的单词逐个加前缀,然后我们在文件上运行perl命令,输入单词存储在变量中。在下面的示例中,read word作为$ word传递给perl命令。

我计划了这项任务,这很快发生了。它是否在我的VM上托管在我的Windows 10上(使用Centos7)。

time cat users.txt |while read word; do  perl -pi -e "s/${word}/ab_${word}/g" data.txt; done        
real    0m1.973s
user    0m1.846s
sys     0m0.127s
$>    
head -2 data.txt  ; echo ; tail -2 data.txt
0|This is a ab_test ab_file ab_maybe
1|This is a ab_test ab_file ab_maybe

499999|This is a ab_test ab_file ab_maybe
500000|This is a ab_test ab_file ab_maybe

在上面的代码中,我们读取了单词:test,file,maybe,并将其更改为data.txt文件中的ab_test,ab_file,ab_maybe。头尾数确认了我们的操作。

欢呼声, 拉夫