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

Macos 不区分大小写的搜索和替换为sed,macos,replace,sed,case-insensitive,Macos,Replace,Sed,Case Insensitive,我正在尝试使用SED从日志文件中提取文本。我可以不费吹灰之力地进行搜索和替换: sed 's/foo/bar/' mylog.txt 但是,我想使搜索不区分大小写。从我在谷歌上搜索到的情况来看,在命令末尾添加I应该可以: sed 's/foo/bar/i' mylog.txt 但是,这给了我一条错误消息: sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i' 这里出了什么问题,我该如何修复它?编者按:这个解决方案在macOS上

我正在尝试使用SED从日志文件中提取文本。我可以不费吹灰之力地进行搜索和替换:

sed 's/foo/bar/' mylog.txt
但是,我想使搜索不区分大小写。从我在谷歌上搜索到的情况来看,在命令末尾添加
I
应该可以:

sed 's/foo/bar/i' mylog.txt
但是,这给了我一条错误消息:

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'
这里出了什么问题,我该如何修复它?

编者按:这个解决方案在macOS上不起作用(开箱即用),因为它只适用于GNU
sed
,而macOS附带BSD
sed

将“I”大写

sed 's/foo/bar/I' file

更新:从macOS Big Sur(11.0)开始,
sed
现在确实支持
I
标志进行不区分大小写的匹配
,因此问题中的命令现在应该可以工作了(BSD
sed
不报告其版本,但您可以查看
man
页面底部的日期,该日期应为2017年3月27日或更晚);一个简单的示例:

#基于macOS Big-Sur及以上版本的BSD(以及Linux上的默认GNU-sed)

$sed's/ö/@/I'Mac版的
sed
似乎有点有限。解决这个问题的一个方法是使用一个linux容器(通过Docker),它有一个可用版本的
sed

cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'

Mac OS X上的
sed
的另一个解决方法是从MacPorts或HomeBrew安装
gsed
,然后创建别名
sed='gsed'
,我也有类似的需求,并提出了以下建议:

此命令仅用于查找所有文件:

grep -i -l -r foo ./* 
要排除此_shell.sh(如果您将命令放在名为this_shell.sh的脚本中),请将输出输入到控制台以查看发生了什么,然后对找到的每个文件名使用sed将文本foo替换为bar:

grep -i -l -r --exclude "this_shell.sh" foo ./* | tee  /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done 
我选择了这种方法,因为我不喜欢更改未修改文件的所有时间戳。输入grep结果只允许查看带有目标文本的文件(因此可能也会提高性能/速度)


请确保备份文件并在使用前进行测试。在某些环境中,可能无法使用嵌入空格的文件。(?

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

/pattern/s/xx/yy/g
然后,您要将
I
放在模式之后:

/pattern/Is/xx/yy/g
例如:

echo Fred | sed '/fred/Is//willma/g'
返回
willma
;如果没有
I
,它将返回未触及的字符串(
Fred
)。

解决了密切相关的不区分大小写的搜索问题。它指出a)许多版本的sed都支持它的标志;b)在sed中执行此操作比较麻烦,您应该使用awk或Perl

但要做到这一点,他们提出了三种选择(此处适用于替代):

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

  • 可能仅限于
    FOO
    FOO
    FOO
    。这些可以由

     s/FOO/bar/;s/[Ff]oo/bar/
    
  • 要搜索所有可能的匹配项,可以对每个字符使用括号表达式:

     s/[Ff][Oo][Oo]/bar/
    

  • 使用以下命令替换所有引用:

    sed 's/foo/bar/gI' mylog.txt
    

    我也看到了,并且试过了。。。但我仍然收到相同的错误消息。BSD sed似乎有很多限制。如果是这样的话,我会用PERL(即PERL-pe's/foo/bar/I')来实现这一点。OS X Lion的默认安装会给出错误:sed:1:“s/foo/bar/I”:替换命令中的错误标志:“I”的
    I
    后缀不是
    sed
    的可移植用法。POSIX
    sed
    仅使用(BRE),其限制令人惊讶。它们甚至不支持
    +
    (您必须使用
    \{1,\}
    ),更不用说不区分大小写的匹配了。使用sed的唯一可移植方法是检查像
    /[hH][eE][lL][lL][oO]/
    这样的东西,这通常是不切实际的。这需要
    /gI
    ,否则它只会在第一次匹配时运行。你能尝试更新你的sed副本吗
    I
    是一个GNU扩展,可能无法与您的sed副本一起使用。编辑:我通过了OS X资格认证,因为OP接受了一个在OS X上不起作用的答案。(正如另一个答案所示,OS X上的sed不支持不区分大小写的匹配,这与苹果的文档相反。)@danorton:谢谢;如果您从以下我的回答中得出这样的感觉,即Apple文档承诺了实现无法提供的东西:
    man sed
    与实现是一致的-没有提到(实际上也没有支持)不区分大小写的匹配;如果您发现一份声明其他内容的文档,请通知我们。@mklement0,是的,对不起,我已更正。苹果的文档并没有声称sed.FWIW是不区分大小写的匹配,这些工具的GNU版本(其BSD版本随OS X一起提供)可从各种软件包管理器获得。我通过安装了一整套文本实用程序,带有
    g
    前缀,因此我可以在需要库存版本中找不到的功能时使用
    gsed
    gdate
    。gsed“s/a/b/Ig”有效,谢谢!为什么一个好的工作答案会被否决?这个答案很好。使用
    brew安装gnu sed
    ,然后转到我的~/.bash_配置文件并添加别名。感谢@davmatBetter使用默认名称
    brew安装gnu-sed——这将覆盖默认的
    sed
    @Mar0ux。使用默认名称
    ——的
    ——现在已被弃用:我将gnu-sed添加到我的路径中,但我相信现在还有其他解决方法:修复区域设置:这是一件特别令人发指的事情。如果有人认真考虑过这一点,只需在本地安装一个GNU-sed。这是一个过份但有用的通用方法!在MacOs上,我得到:
    sed:1:“/fred/Is//willma/g”:无效的命令代码I
    好提示。这是
    sed 's/foo/bar/gI' mylog.txt