我正试图找到一种方法来删除第一个单词IF中的所有字符,该字符位于第二个单词中。输入如下所示:
电脑费用
结果应该是:“mpuer”因为c,o和t被删除了。这样的多行由返回分隔,2个单词用空格分隔。
我一直在寻找解决方案,但我真的被卡住了。感谢所有帮助。
答案 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)
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
,则第三行分支到标签,因此在替换命令找到要执行的操作时建立循环。一旦循环完成,最后一行将删除空格后的单词。
现在所有的目光都集中在正则表达式上。关键的见解是,您可以使用\n
在n
中查找字符串后面的重复记忆模式,其中\2
是一个数字。正则表达式的第一部分将该行分为5个部分。第一部分是一个(可能是空的)字母序列,不感兴趣;第二个是有趣的单个字母;第三个是另一个(可能是空的)字母序列,它们并不有趣;第四个是将第一个单词与第二个单词分开的空格。最后一部分本身可以细分为3个部分,尽管它们都被组合在一起形成一个捕获表达式。它由一系列零个或多个不感兴趣的字母组成,重复一行中第一个单词的有趣字母(c
),以及零个或多个无趣字母的另一个序列。
替换字符串保留第一个单词的前后部分,加上空格和第二个单词。
在组合中,它会依次找到每个字母o
,t
和sed
,从第一个单词中删除它们,而在第二个单词中将它们单独排除。
$ 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