在loop中仅将sed应用于文件中最后一次匹配之后的部分- shell / bash [closed]

wvyml7n5  于 7个月前  发布在  Shell
关注(0)|答案(2)|浏览(46)

已关闭。此问题需要details or clarity。目前不接受回答。
**要改进此问题吗?**通过editing this post添加详细信息并阐明问题。

4小时前关闭
Improve this question
我有几个这样结构的大文件(~1Gb):

fooA iug9wa
fooA lauie
fooA nwgoieb
fooB wilgb
fooB rqgebepu
fooB ifbqeiu
...
fooN ibfiygb
fooN yvsiy
fooN aeviu

字符串
我想在shell中替换每个fooX(其中包含字母,数字“.”和“_”),(我在foo.list中列出了所有)顺序编号1到N。
我用过:

nfoos=$(wc -l < foo.list)

for i in $(seq 1 $nfoos)
do
    currentfoo=$(sed "${i}q;d" foo.list)
    sed -i "s/"${currentfoo}"/$i/g" file1
    sed -i "s/"${currentfoo}"/$i/g" file2
    sed -i "s/"${currentfoo}"/$i/g" filen
done


然而,对于大文件来说,这将花费很长时间。由于每个连续的fooX总是出现在文件中,而不是foo(X-1),我想让sed只搜索fooX最后一次匹配之后的fileX部分,这样每个foo都有更少的空间可以搜索。我一直在尝试使用标签和一些多行方法,但语法一直困扰着我。
有人知道如何使它工作吗?(不一定要使用sed,但如果它能在Bash的基本shell中工作就好了。
感谢任何帮助。如果你这样做,请解释每个函数/选项/变量使用,这样我就可以找出我一直在搞砸。

zpjtge22

zpjtge221#

您可以使用awk
下一个awk命令的第一部分将填充数组a,第二部分将替换第一个字。

awk 'NR==FNR { a[$1]=NR; next} $1 in a{$1=a[$1]; print}' foo.list file1

字符串
如果你喜欢这样,你可以在你的文件上循环

for f in file1 file2 filen; do
  awk 'NR==FNR { a[$1]=NR; next} $1 in a{$1=a[$1]; print}' foo.list "${f}" > "${f}.tmp" &&
  mv "${f}.tmp" "${f}"
done


&&确保新文件只会在awk正常时替换原始文件。

mwecs4sa

mwecs4sa2#

两个优化:
1.使用awk生成一个sed脚本,它可以在一次运行中完成所有的替换。
1.使用N个文件参数运行sed -i,而不是每次使用1个文件参数运行sed N次。

awk '{ print "s/" $0 "/" NR "/g;" }' foo.list > temp_script
sed -i -f temp_script $(cat foo.list)

字符串
现在只需运行一次sed,而不是N^2次。

相关问题