sed+awk 能不能实现根据多列数据批量替换?

2015-12-08 15:00:11 +08:00
 v2htm
awk 看起来非常强大,不过有个需求我用 awk 实现不了,难道 awk 做不到?
string.txt 包含如下列:
1 word WORD
2 test TEST
3 this THIS
……

foo.txt 内容:
this is a word replace test.

替换成:
<3>thisTHIS is a <1>wordWORD replace <3>testTEST.
3182 次点击
所在节点    程序员
10 条回复
uuspider
2015-12-08 15:57:52 +08:00
一行一行地正则+替换呗,不过,为啥必须 sed+awk?
v2htm
2015-12-08 16:11:49 +08:00
@uuspider 列表很长,文件很多啊,必须批量替换
你觉得其他工具用什么最合适?
SpicyCat
2015-12-08 17:02:50 +08:00
楼主的需求我都没看懂。
lululau
2015-12-08 17:25:53 +08:00
如果不考虑标点的话:

gawk -v FS='[^0-9a-zA-Z]' 'NR==FNR { d[$2]="<"$1">"$2$3; next}; {for(i=1;i<=NF;i++) { if(d[$i]) $i = d[$i]};print}' string.txt foo.txt

如果要考虑保留标点,我觉得用 awk 写有点太复杂了,建议用 Perl/Ruby :

ruby -pe 'BEGIN{$d=IO.readlines("./string.txt").map(&:split).each_with_object({}){|l,h|h[l[1]]="<%s>%s%s"%l}};gsub(/\w+/) {|s|$d[s]||s}' foo.txt
reticentfat
2015-12-08 18:10:02 +08:00
仔细看了三遍没看懂需求
jings
2015-12-08 18:18:11 +08:00
看了下规律 应该是下面的对应关系吧
var string={
test: "<2>testTEST",
this:"<3>thisTHIS",
word:"<1>wordWORD",
}
binux
2015-12-08 18:31:29 +08:00
echo "this is a word replace test." | awk 'BEGIN { while (getline < "string.txt") { s[$2]="<"$1">"$2$3 } } { for (k in s) { sub(k, s[k], $0) } print $0; }'
xufang
2015-12-08 18:41:20 +08:00
列表如果数量不大的话,比如在 2~3 万行,直接用 sublime 的列编辑和正则功能,秒杀之。
比写脚本还少了调试步骤,又快又直观。
v2htm
2015-12-08 21:01:13 +08:00
非常感谢大家!
@SpicyCat @reticentfat 主要是为了直观起见例子举得毫无可读性和实际意义,实际用途是转换电子书时候批量添加注释:根据一个三列的列表,用第二列匹配若干 html 文件内的字符串,前后分别插入第一列和第三列,实际比这个复杂一点,但核心就是这个。用 sed awk 是因为别的语言我更陌生,自己没法进一步修改。

@lululau 因为必须要保留标点,所以 awk 那条没测试, ruby 的测试没问题,我只了解一点 sed 和 awk ,其他语言没法自己根据实际需求进一步完善,既然 ruby 这么高效,我还是研究一下!

@binux 匆忙测试了一下,输出结果还是原文,是不是要用 gsub ?
binux
2015-12-08 21:12:16 +08:00
@v2htm 我只保证在你给的例子中有效

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/241996

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX