我试图find一种方法来删除第一个单词中的所有字符,如果该字符在第二个单词中。 input如下所示:
电脑成本
结果应该是:“mpuer”,因为c,o和t被删除了。 有多行这样分隔的回车,这两个词是由一个空格分隔。
我一直在寻找相当一段时间的解决scheme,但我真的被卡住了。 所有的帮助表示赞赏。
这可能适合你:
echo "computer cost" | sed ':a;s/\(.\)\(.* .*\1.*\)/\2/;ta;s/ .*//' mpuer
说明:
:a;
s/\(.\)\(.* .*\1.*\)/\2/
相同字符匹配的字符s/\(.\)\(.* .*\1.*\)/\2/
ta
s/ .*//
替代正则表达式可以进一步解释:
\(.\)
匹配单词1中的任何字符(以后称为\1
) \(.* .*\1.*\)
匹配一个单词的其余部分中的任何字符.*
后跟一个空格
然后在第二个字母上有一个没有字符的字符.*
接着是从第一个字符开始的匹配字符,然后是第二个字符剩下的字符。 \2
从而有效地删除匹配字符\1
这工作(像potong的解决方案 一样 ):
sed -e ': loop' \ -e 's/\([az]*\)\([az]\)\([az]*\) \([az]*\2[az]*\)/\1\3 \4/' \ -e 't loop' \ -e 's/ .*//' \ "$@"
第一行建立一个标签。 第三行分支到标签,如果自从行被读取并且最后一次执行t
已经有成功的替换,那么在替换命令找到要做的事情时建立一个循环。 循环完成后,最后一行删除空格后面的单词。
现在,所有的眼神都集中在正则表达式上。 关键的见解是,你可以在字符串后面使用\n
来查找重复的记忆模式,其中n
是一个数字。 正则表达式的第一部分将行分成5个部分。 第一部分是一个(可能是空的)不感兴趣的字母序列; 第二个是有趣的单个字母; 第三个是另一个(可能是空的)不感兴趣的字母序列; 第四个是把第一个词和第二个词分开的空间。 最后一部分本身可以细分为三部分,尽管它们都被组合成一个捕获表达式。 它由零个或多个不感兴趣的字母序列组成,重复来自该行上第一个单词( \2
)的有趣字母,以及另一个零个或多个不感兴趣的字母序列。
替换字符串保留第一个单词的前后部分,加上空格和第二个单词。
结合起来,它依次找到每个字母c
, o
和t
,从第一个单词中消除它们,并将它们单独留在第二个单词中。
sed
的条件分支是很难使用的,但它可以真正得分。 当你的双手被这样的任务所束缚时,这使解决方案变得可行。
$ al 'computer cost' 'encyclopedia brittanica' 'security privacy' | > sed -e ': loop; s/\([az]*\)\([az]\)\([az]*\) \([az]*\2[az]*\)/\1\3 \4/; t loop' mpuer eyloped seut $
al
只是每行列出一个参数 – 因此,助记符参数列表:
#include <stdio.h> int main(int argc, char **argv) { while (*++argv) puts(*argv); return 0; }
Potong的解决方案基本上等同于我的“Code Golf”版本:
sed ':a;s/\(.\)\(.* .*\1.*\)/\2/;ta;s/ .*//'
它使用与我一样的通用技术,但简化了正则表达式。 一个简化就是使用.
(任何字符)代替[az]
(任何字母)。 另一个是认识到领先模式并不重要; 它将被单独留下。 最后是将第一个单词的尾部与第二个单词的尾部分组。 回想起来,我可以(应该?)为我的模式添加了一个锚点。 波东的标签简直就是a
。
基本上你是通过tr
。
echo computer cost | while read xy;do echo $x | tr -d $y ; done;
如果你有一个文件( words
)像
computer cost computer mop
以下命令将进行更换。
while read xy; do echo $x | tr -d $y ; done< words
如果你想使用sed
只需用sed s/[$y]//g
替换tr -d $y