【发布时间】:2015-04-23 20:08:50
【问题描述】:
for term in `cat stopwords`; do sed -i 's/\<$term\>//g' spam.txt ;done
鉴于停用词每行包含一个单词,而 spam.txt 是纯文本文件,我只需要替换停用词的完全匹配项。不符合我的预期......
请注意,两个文件中都有doesn't、couldn't 之类的词。
【问题讨论】:
for term in `cat stopwords`; do sed -i 's/\<$term\>//g' spam.txt ;done
鉴于停用词每行包含一个单词,而 spam.txt 是纯文本文件,我只需要替换停用词的完全匹配项。不符合我的预期......
请注意,两个文件中都有doesn't、couldn't 之类的词。
【问题讨论】:
您确定要在 for 循环中运行 sed 吗?我会使用 sed 脚本文件。
TMPFILE=mktemp
for WORD in $(cat stopwords); do echo 's/'$WORD'//g' >> $TMPFILE; done
sed -f $TMPFILE spam.txt
rm -f $TMPFILE
【讨论】:
sed -i -f $TMPFILE spam.txt - 从而保持 OP 执行就地替换的意图,只是更有效地使用脚本文件。
sed生成$TMPFILE:sed 's|^|s/|;s|$|//g|' stopwords > $TMPFILE。然后实际直接作为脚本使用:sed 's|^|s/|;s|$|//g|' stopwords | sed -i -f - spam.txt
你应该在 sed 命令中使用 " 而不是 '。使用单引号 ' 告诉 shell 不要替换 $term。
这个:
for term in `cat stopwords`; do sed -i "s/\<$term\>//g" spam.txt ;done
适用于:
# stopwords
couldn't
和:
# spam.txt
foo <couldn't> bar
我的 2 美分
【讨论】:
@kerolasa 正在做某事。
最重要的是您的 $term 没有被扩展为变量。您可以将代码重写为
for term in `cat stopwords`; do sed -i "s/\<${term}\>//g" spam.txt ;done
但这是一个非常昂贵的操作,您正在为stopwords 中的每个单词运行 sed。根据@kerolasa 的想法制作一个 sed 脚本更有效,但这取决于,如果这是一个一次性项目,那么您的解决方案将起作用。
除了...“两个文件中的“不”、“不能”之类的词,是的,还有?我不确定你在说什么,你期望/想要发生什么,为什么你认为它不会发生?更改您的报价会有所帮助。
最后,请注意,如果您的停用词列表包含空格,即“工作中的扳手”;-),此解决方案可能会中断。
我希望这会有所帮助。
【讨论】:
除了使用Sami Kerola 建议的脚本临时文件,您还可以将脚本通过管道传送到sed,使用sed 的第二个实例从stopwords 创建它:
sed 's,.*,s/\\<&\\>//g,' stopwords | sed -i -f- spam.txt
请注意,我使用, 而不是/ 作为sed 的第一个实例的分隔符,以便不必引用我在生成的表达式中用作分隔符的每个/。但恕我直言,这只是个人喜好问题,当然你也可以使用's/.*/s\/\\<&\\>\/\/g/',如果你更喜欢它。
【讨论】: