我意识到标题是可怕的,但无论如何,我有一个任务,把所有的实例“猫”改为“狗”使用sed。很简单,但它也包括“弹射器”和“熊猫”这样的词,我试图通过在代码中添加一个空格来避免它们。我的问题是,每个词都变成“狗”,在某些情况下,我希望它是“狗”或“狗”.
下面是我要更改的文本文件:
亲爱的房主, 猫对人很重要。我们都喜欢猫的陪伴。如果你想养一只猫,我们可以帮忙。我们正试图为我们的城市举办一个“猫回家”的日子。为了帮助我们,我们已经征集了NWMSU的熊啦啦队长,这个城市一年一度的弹射器投掷的组织者,和当地的名人帮助为猫寻找家。 有一只猫需要你为它们提供一个家。所以,如果你是一个爱猫的人,请过来看看有没有办法在你的心里找到一个猫的家。 谢谢!! 猫也是人。
这是我得到的输出,这显然是错误的
亲爱的房主, 狗对人很重要。我们都喜欢猫的陪伴。如果你想养一只猫,我们可以帮忙。我们正试图为我们的城市举办一个“猫回家”的日子。为了帮助我们,我们已经征集了NWMSU的熊啦啦队长,这个城市一年一度的弹射器投掷的组织者,和当地的名人帮助为猫寻找家。 有一只猫需要你为它们提供一个家。所以,如果你是一个爱猫的人,请过来看看有没有办法在你的心里找到一个猫的家。 谢谢!! 狗也是人。
这是我的密码:
sed 's/[Cc]at[s] /dog /g' cats-dogs.txt 发布于 2015-04-08 22:47:56
我很肯定,你不能单用一个RegEx就能做到这一点。
尽管如此,简单的解决方案在这里可能是最好的,因为只有两种可能的情况(上和下)和一个替换词,它似乎(同时sed允许多个替换容易)。
因此,这样的东西应该可以工作(假设GNU ):
sed -r 's/\bCat(s?)\b/Dog\1/g; s/\bcat(s?)\b/dog\1/g' cats-dogs.txt使用扩展的regexp,因为在命令行上引用并不那么可怕。请注意这里的字词边界扫描。
可能有一种非常聪明(且不可读)的sed方法可以使用\u和缓冲区来实现这一点。
发布于 2015-04-08 22:57:39
到目前为止,让我们分析一下您的尝试。
s/[Cc]at[s] /dog /g这将搜索regex [Cc]at[s]并替换dog。有几个原因不起作用..。
[s]的意思是“字母s”。如果您正在使用Linux,那么在您的系统上安装的sed版本可能是GNU,下面的内容可能有效:
sed -r 's/\bcat(s?)\b/dog\1/g;s/\bCat(s?)\b/Dog\1/g'注意-r选项,它告诉sed使用“扩展”正则表达式表示法,而不是默认的“基本”表示法。
此解决方案依赖sed对\b单词边界的理解,但需要注意的是,在其他操作系统(FreeBSD、OSX、Solaris等)上的sed实现中并不普遍可用这一缩写。如果可移植性很重要,请避免使用\b和类似的东西。
这个速记很好,但真的不需要。在BRE中也有一样的东西:
sed 's/[[:<:]]cat\(s*\)[[:>:]]/dog\1/g;s/[[:<:]]Cat\(s*\)[[:>:]]/Dog\1/g'这是BRE而不是ERE,所以我们不使用-r选项。我应该指出,这也将与"catssss“相匹配,因为我们使用的是s*而不是s?。许多sed实现中的BRE并不包括只识别一个原子的一种方法。
传统的类[[:<:]]和[[:>:]]适用于单词的开头或结尾,有时比GNU的“单词边界”更好,后者可以用于单词的开头或结尾。
在任何带有man re_format的unix上都可以看到非GNU格式。
(注意到:sed的-r选项也不是通用的。在OSX中,使用-E代替。这是因为OSX的sed是从较早版本的FreeBSD派生而来的,后者仅在几个版本之前添加了-r作为-E的等效选项。)
发布于 2015-04-09 01:16:26
使用perl,但它并不漂亮:
perl -pe 's/\b(c)at(?=s?\b)/ $1 =~ m{[[:upper:]]} ? "Dog" : "dog" /ige' <<END
scat cat cats Cats Cat Catskills
END输出
scat dog dogs Dogs Dog Catskills https://stackoverflow.com/questions/29526457
复制相似问题