shell – SED或AWK用另一个文件中的模式替换所有模式

前端之家收集整理的这篇文章主要介绍了shell – SED或AWK用另一个文件中的模式替换所有模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试使用SED脚本进行模式替换,但它无法正常工作

sample_content.txt

288Y2RZDBPX1000000001dhana
JP2F64EI1000000002d
EU9V3IXI1000000003dfg1000000001dfdfds
XATSSSSFOO4dhanaUXIBB7TF71000000004adf
10Q1W4ZEAV18LXNPSPGRTTIDHBN1000000005egw

patterns.txt

1000000001 9000000003
1000000002 2000000001
1000000003 3000000001
1000000004 4000000001
1000000005 5000000001

预期产出

288Y2RZDBPX9000000003dhana
JP2F64EI2000000001d
EU9V3IXI3000000001dfg9000000003dfdfds
XATSSSSFOO4dhanaUXIBB7TF74000000001adf
10Q1W4ZEAV18LXNPSPGRTTIDHBN5000000001egw

我可以用单个SED替换像

sed  's/1000000001/1000000003/g' sample_content.txt

注意:

>匹配模式不在固定位置.
>单行可能有多个匹配值要在sample_content.txt中替换
> Sample_content.txt和patterns.txt具有> 1百万条记录

文件附件链接https://drive.google.com/open?id=1dVzivKMirEQU3yk9KfPM6iE7tTzVRdt_

谁能建议如何在不影响性能的情况下实现这一目标

更新于2018年2月11日

在分析了真实文件后,我得到了一个提示,即在第30和第31位有一个等级值.这有助于我们在需要的地方和所有地方申请更换.
如果是AB级,则在41-50和101-110处替换10位数的电话号码
如果等级BC,则在11-20,61-70和151-160处替换10位数的电话号码
如果是DE级,则将1-10位电话号码替换为1-10,71-80,151-160和181-190

像这样,我看到了200个样本记录的50个独特等级.

{   grade=substr($0,110,2)} // identify grade
{ 
    if (grade == "AB") {
        print substr($0,41,10) ORS substr($0,101,10)
    } else if(RT == "BC"){
        print substr($0,11,61,151,10) 
    }

    like wise 50 coiditions
}

我可以知道,这种方法是否可取或更好的方法

未来参考的基准

测试环境:

使用样本文件patterns.txt包含50,000行和contents.txt也包含50,000行.

来自patterns.txt的所有行都加载到所有解决方案中,但只检查了前1000行的contents.txt.

测试笔记本电脑配备双核64位Intel(R)Celeron(R)cpu N3050 @ 2.16GHz,4 GB RAM,Debian 9 64位测试,gnu sed 4.4和gnu awk 4.1.4

在所有情况下,输出都被发送到新文件,以避免在屏幕上打印数据的开销很慢.

结果:

1. RavinderSingh13第一个awk解决方

$time awk 'FNR==NR{a[$1]=$2;next}   {for(i in a){match($0,i);val=substr($0,RSTART,RLENGTH);if(val){sub(val,a[i])}};print}' patterns.txt  <(head -n 1000 contents.txt) >newcontents.txt

real    19m54.408s
user    19m44.097s
sys 0m1.981s

2. EdMorton 1st awk解决方

$time awk 'NR==FNR{map[$1]=$2;next}{for (old in map) {gsub(old,map[old])}print}' patterns.txt <(head -n1000 contents.txt) >newcontents.txt

real    20m3.420s
user    19m16.559s
sys 0m2.325s

3. Sed(我的sed)解决方

$time sed -f <(printf 's/%s/%s/g\n' $(<patterns.txt)) <(head -n 1000 contents.txt) >newcontents.txt

real    1m1.070s
user    0m59.562s
sys 0m1.443s

4. Cyrus sed解决方

$time sed -f <(sed -E 's|(.*) (.*)|s/\1/\2/|g' patterns.txt) <(head -n1000 contents.txt) >newcontents.txt

real    1m0.506s
user    0m59.871s
sys 0m1.209s

5. RavinderSingh13第二个awk解决方

$time awk 'FNR==NR{a[$1]=$2;next}{for(i in a){match($0,a[i]);print;next}};}1' patterns.txt  <(head -n 1000 contents.txt) >newcontents.txt

real    0m25.572s
user    0m25.204s
sys     0m0.040s

对于少量输入数据,如1000行,awk解决方案似乎很好.
让我们这次用9000行进行另一次测试以比较性能

6.RavinderSingh13第二个awk解决方案,9000行

$time awk 'FNR==NR{a[$1]=$2;next}{for(i in a){match($0,a[i]);print;next}};}1' patterns.txt  <(head -9000 contents.txt) >newcontents.txt

real    22m25.222s
user    22m19.567s
sys      0m2.091s

7.具有9000行的Sed溶液

$time sed -f <(printf 's/%s/%s/g\n' $(<patterns.txt)) <(head -9000 contents.txt) >newcontents.txt

real    9m7.443s
user    9m0.552s
sys     0m2.650s

8.具有9000条线的平行Seds解决方

$cat sedpar.sh
s=$SECONDS
sed -f <(printf 's/%s/%s/g\n' $(<patterns.txt)) <(head -3000 contents.txt) >newcontents1.txt &
sed -f <(printf 's/%s/%s/g\n' $(<patterns.txt)) <(tail +3001 contents.txt |head -3000) >newcontents2.txt &
sed -f <(printf 's/%s/%s/g\n' $(<patterns.txt)) <(tail +6001 contents.txt |head -3000) >newcontents3.txt &
wait
cat newcontents1.txt newcontents2.txt newcontents3.txt >newcontents.txt && rm -f newcontents1.txt newcontents2.txt newcontents3.txt
echo "seconds elapsed: $(($SECONDS-$s))"

$time ./sedpar.sh
seconds elapsed: 309

real    5m16.594s
user    9m43.331s
sys     0m4.232s

将任务拆分为更多命令(如三个并行seds)似乎可以加快速度.

对于那些想在自己的PC上重复基准的人,你可以通过OP的链接或我的github下载文件contents.txt和patterns.txt:

contents.txt

patterns.txt

猜你在找的Bash相关文章