不区分大小写的搜索和替换为sed

Cra*_*ker 74 macos replace sed case-insensitive

我正在尝试使用SED从日志文件中提取文本.

我可以毫不费力地进行搜索和替换:

sed 's/foo/bar/' mylog.txt
Run Code Online (Sandbox Code Playgroud)

但是,我想使搜索不区分大小写.从我用Google搜索的内容看起来,附加i到命令的末尾应该可以正常工作:

sed 's/foo/bar/i' mylog.txt
Run Code Online (Sandbox Code Playgroud)

但是,这给了我一个错误消息:

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'
Run Code Online (Sandbox Code Playgroud)

这里出了什么问题,我该如何解决?

我在macOS上,万一重要.

mkl*_*nt0 68

要明确:在macOS上 - 从Mojave(10.14) - sed- 这是BSD实现 - 不支持不区分大小写的匹配 - 很难相信,但却是真的.在以前接受的答案,这本身就说明一个GNU sed命令,获得因为这种地位perl在评论中提到基于解决方案.

为了让这个Perl的解决方案与工作外文字符,以及通过UTF-8,使用这样的:

perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
Run Code Online (Sandbox Code Playgroud)
  • -C 假设当前区域设置是基于UTF-8的,则启用对流和文件的UTF-8支持.
  • -Mutf8告诉Perl将源代码解释为UTF-8(在这种情况下,传递给的字符串-pe) - 这是更详细的更短的等效-e 'use utf8;'.谢谢,Mark Reed

(注意,使用awk也不是一个选项,因为awk在macOS上(即BWK awk,又名BSD awk)似乎完全没有意识到语言环境 - 它tolower()toupper()函数忽略外来字符(和sub()/ gsub()没有不区分大小写的标志)首先).)


Wes*_*ice 60

编者注:此解决方案不适用于macOS(开箱即用),因为它仅适用于GNU sed,而macOS附带BSD sed.

资本化'我'.

sed 's/foo/bar/I' file
Run Code Online (Sandbox Code Playgroud)

  • 看来,BSD sed有很多局限性.如果是这样的话,我会在PERL(即perl -pe的/ foo/bar/i')中执行此操作. (14认同)
  • `I`后缀不是`sed`的便携式使用.POSIX`sed'只使用[基本正则表达式](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_03)(BRE),这些都令人惊讶地受到限制.它们甚至不支持`+`(你必须使用`\ {1,\}`代替),更不用说不区分大小写的匹配了.使用sed执行此操作的唯一可移植方法是检查类似`/ [hH] [eE] [lL] [lL] [oO] /`的内容,这通常是不切实际的. (12认同)
  • 这需要是`/ gI,否则它只会在第一场比赛中运作. (4认同)
  • OS X Lion的默认安装错误:sed:1:"s/foo/bar/I":替换命令中的错误标志:'我' (3认同)
  • 我也看到了这一点,并尝试了...但我仍然得到相同的错误信息. (2认同)

小智 23

sedMac OS X的另一个解决方法是gsed从MacPorts或HomeBrew 安装,然后创建别名sed='gsed'.

  • 最好做'brew install gnu-sed --with-default-names` - 这将覆盖默认的`sed`. (6认同)
  • 这个答案很棒.使用`brew install gnu-sed`然后转到我的〜/ .bash_profile并添加了别名.谢谢@davmat (3认同)

小智 8

如果您首先进行模式匹配,例如,

/pattern/s/xx/yy/g
Run Code Online (Sandbox Code Playgroud)

然后你想把它放在I模式后面:

/pattern/Is/xx/yy/g
Run Code Online (Sandbox Code Playgroud)

例子:

echo Fred | sed '/fred/Is//willma/g'
Run Code Online (Sandbox Code Playgroud)

返回willma;如果没有I,它将返回原样的字符串 ( Fred)。

  • 在 MacO 上,我得到: `sed: 1: "/fred/Is//willma/g": invalid command code I` (2认同)

Ben*_* W. 5

sed的FAQ地址密切相关的不区分大小写的搜索。它指出 a) sed 的许多版本都支持它的标志,b) 在 sed 中这样做很尴尬,您应该使用 awk 或 Perl。

但是要在POSIX sed 中做到这一点,他们建议了三个选项(适用于此处的替换):

  1. 转换为大写并将原始行存储在保持空间中;但是,这不适用于替换,因为原始内容将在打印之前恢复,因此它仅适用于基于不区分大小写的匹配插入或添加行。

  2. 也许可能性仅限于FOO,Foofoo。这些可以覆盖

     s/FOO/bar/;s/[Ff]oo/bar/
    
    Run Code Online (Sandbox Code Playgroud)
  3. 要搜索所有可能的匹配项,可以对每个字符使用括号表达式:

     s/[Ff][Oo][Oo]/bar/
    
    Run Code Online (Sandbox Code Playgroud)