Macos 不区分大小写的搜索和替换为sed
我正在尝试使用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 '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上不起作用(开箱即用),因为它只适用于GNUsed
,而macOS附带BSDsed
将“I”大写
sed 's/foo/bar/I' file
更新:从macOS Big Sur(11.0)开始,
sed
现在确实支持I
标志进行不区分大小写的匹配,因此问题中的命令现在应该可以工作了(BSDsed
不报告其版本,但您可以查看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
的可移植用法。POSIXsed
仅使用(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