如果它们也在下一个单词(sed)中,如何从单词中删除字符?

时间:2012-02-19 13:22:09

标签: linux sed

我正试图找到一种方法来删除第一个单词IF中的所有字符,该字符位于第二个单词中。输入如下所示:

电脑费用

结果应该是:“mpuer”因为c,o和t被删除了。这样的多行由返回分隔,2个单词用空格分隔。

我一直在寻找解决方案,但我真的被卡住了。感谢所有帮助。

3 个答案:

答案 0 :(得分:6)

这可能对您有用:

echo "computer cost" |
sed ':a;s/\(.\)\(.* .*\1.*\)/\2/;ta;s/ .*//'
mpuer

说明:

  • 为将来的分支命令:a;
  • 制作标签
  • 删除第一个单词中与第二个单词s/\(.\)\(.* .*\1.*\)/\2/
  • 中相同字符匹配的字符
  • 如果替换发生分支到标签ta
  • 当没有更多替换时删除第二个单词。 s/ .*//

可以进一步解释替换正则表达式:

  • \(.\)匹配第一个字词中的任何字符(后来称为\1
  • \(.* .*\1.*\)匹配单词.*的其余部分中的所有字符,后跟空格,后跟单词二.*中的一些字符,后跟匹配单词\1中的字符后跟单词2 .*中剩余的字符,此分组稍后将称为\2
  • 如果以上匹配项将其替换为\2,则会有效删除匹配的字符\1

答案 1 :(得分:3)

这是有效的(solution除了potong):

sed -e ': loop' \
    -e 's/\([a-z]*\)\([a-z]\)\([a-z]*\) \([a-z]*\2[a-z]*\)/\1\3 \4/' \
    -e 't loop' \
    -e 's/ .*//' \
    "$@"

第一行建立标签。如果读取了行并且最后一次执行t,则第三行分支到标签,因此在替换命令找到要执行的操作时建立循环。一旦循环完成,最后一行将删除空格后的单词。

现在所有的目光都集中在正则表达式上。关键的见解是,您可以使用\nn中查找字符串后面的重复记忆模式,其中\2是一个数字。正则表达式的第一部分将该行分为5个部分。第一部分是一个(可能是空的)字母序列,不感兴趣;第二个是有趣的单个字母;第三个是另一个(可能是空的)字母序列,它们并不有趣;第四个是将第一个单词与第二个单词分开的空格。最后一部分本身可以细分为3个部分,尽管它们都被组合在一起形成一个捕获表达式。它由一系列零个或多个不感兴趣的字母组成,重复一行中第一个单词的有趣字母(c),以及零个或多个无趣字母的另一个序列。

替换字符串保留第一个单词的前后部分,加上空格和第二个单词。

在组合中,它会依次找到每个字母otsed,从第一个单词中删除它们,而在第二个单词中将它们单独排除。

$ al 'computer cost' 'encyclopedia brittanica' 'security privacy' | > sed -e ': loop; s/\([a-z]*\)\([a-z]\)\([a-z]*\) \([a-z]*\2[a-z]*\)/\1\3 \4/; t loop' mpuer eyloped seut $ 中的条件分支很难使用,但它偶尔会得分。当你的手被这样的任务束缚时,它使解决方案成为可能。

al

#include <stdio.h> int main(int argc, char **argv) { while (*++argv) puts(*argv); return 0; } 只是每行列出一个参数 - 因此助记符参数列表:

sed ':a;s/\(.\)\(.* .*\1.*\)/\2/;ta;s/ .*//'

Potong的解决方案基本上相当于我的“Code Golf”版本:

.

它使用与我相同的一般技术,但简化了正则表达式。一个简化是使用[a-z](任何字符)代替^(任何字母)。另一个是认识到领先模式并不重要;它将被遗弃。最后一个是将第一个单词的尾部与整个第二个单词的尾部分组。回想起来,我可以(应该?)在我的模式中添加a锚点。 Potong的标签只是{{1}}。

答案 2 :(得分:1)

基本上你是通过tr;

来做到的
echo computer cost | while read x y;do echo $x |  tr -d $y ; done;

如果你有一个文件(words),比如

computer cost
computer mop

以下命令将进行替换。

while read x y; do echo $x |  tr -d $y ; done< words

如果您想使用sed,只需将tr -d $y替换为sed s/[$y]//g