我想创建一个正则表达式,它可以替换包含两个以大写字母开头的单词的行,字符"X"。
我目前正在使用这个:
sed -e '/b[A-Z][a-z]*b c X /home/Morgan/desktop/test
问题如下:它只更改包含 1 个或多个由我的test.txt
正则表达式描述的单词的行。
我不知道怎么说我只想要一个 X 在正好 2 个以大写开头的单词的行上。任一单词都可以出现在行中的任何位置。
我的测试.txt包含:
Bonjouroui oui Bonjour -> 这必须替换为 X
Bonjour Bonjour Bonjour ->这不能
Bonjour Oui bonjour oui -> 这必须替换为 X
您似乎试图使用 Perl/PCRE 字边界b
但典型的sed
实现不理解这种正则表达式方言。 无论如何,通过您的问题描述,您正在寻找行的开头和结尾;这是一个非常基本的正则表达式锚点,已经在原始grep
中引入:^
匹配行首,$
匹配行尾。
如果没有锚点,正则表达式将匹配行中的任何位置。要说"只有两个",你真的必须检查整条线,并确保没有三个或更多你要找的东西。
"找到一行正好有两个以大写开头的单词"需要稍微改写或按摩一下,然后才能尝试编写正则表达式。 如果我们暂时地将w
定义为"不以大写开头的单词",W
定义为以大写开头的单词,则需要^w*Ww*Ww*$
- 正好是两个大写单词,以及零个或多个非大写单词在它们之前,之间或之后的任何位置。
以大写开头的单词是[A-Z][a-z]*
(这要求所有后续字符都是小写的),一个不以大写开头的单词是[a-z][a-z]*
的(如果您的sed
支持该正则表达式变体,则[a-z]+
)。
由于单词之间需要空格,因此需要将可选的单词表达式括起来,以便您可以说"整个序列中的零个或多个"。通常,sed
正则表达式也需要将括号分组反斜杠,尽管这在版本之间有所不同。
所以,试试这个:
sed 's/^([a-z][a-z]* )*[A-Z][a-z]*( [a-z][a-z]*)* [A-Z][a-z]*( [a-z][a-z]*)*$/X/' file
如果你确实有GNUsed
,这可以简化一点:
sed -r 's/^([a-z]+ )*[A-Z][a-z]*( [a-z]+)* [A-Z][a-z]*( [a-z]+)*$/X/' file
这个"词"的定义可能还不够;也许你可以改进它以适应你的情况。 特别是,假定间距是规则的(单词之间正好是一个空格;行上没有前导或尾随空格),并且任何文本都不能包含空格以外的字符,字母 a-z 为大写或小写。(重音字符(如 è 和 Á)是否也被视为此范围内的字母,取决于您的区域设置。如果法语区域设置很重要,可以在脚本中设置LC_ALL=fr_FR.utf-8
。
另请注意sed
substition 命令如何恰好需要三个分隔符 - 传统上,我们使用斜杠,但您可以使用任何标点字符。表单是s/regex/replacement/flags
,其中正则表达式、替换和标志都可以为空,但始终需要s
和分隔符。