不区分大小写的搜索&用sed替换

时间:2010-12-10 20:20:44

标签: macos replace sed case-insensitive

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

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

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

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

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

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

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'

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

我在使用macOS,以防万一。

9 个答案:

答案 0 :(得分:63)

要明确:在 macOS - 从Mojave(10.14)开始 - sed - 这是 BSD 实施 - 不支持案例 - 敏感匹配 - 很难相信,但却是真的。由于评论中提到的基于sed的解决方案,formerly accepted answer本身显示了 GNU perl命令,因此获得了该状态。

要使 Perl解决方案外国字符一起使用,通过UTF-8,请使用以下内容:

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

(请注意使用awk不是的选项,而是macOS上的awk(即 BWK awk ,又名 BSD awk )似乎完全没有意识到语言环境 - 它的tolower()toupper()函数忽略了外来字符(并且sub() / gsub()没有案例 - 开始的 - 不敏感标志)。)

答案 1 :(得分:59)

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

将'我'大写。

sed 's/foo/bar/I' file

答案 2 :(得分:23)

Mac OS X上define('YII_DEBUG', false);的另一种解决方法是从MacPorts或HomeBrew安装sed,然后创建别名gsed

答案 3 :(得分:2)

sed FAQ解决了紧密相关的不区分大小写的 search 。它指出:a)许多版本的sed支持它的标志,b)在sed中这样做很尴尬,您应该使用awk或Perl。

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

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

  2. 也许可能性仅限于FOOFoofoo。这些可以通过

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

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

答案 4 :(得分:1)

sed的Mac版似乎有点受限。解决此问题的一种方法是使用具有可用版本sed的Linux容器(通过Docker):

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

答案 5 :(得分:0)

我有类似的需求,并想出了这个:

这个命令只是找到所有文件:

grep -i -l -r foo ./* 

这个要排除this_shell.sh(如果你将命令放在一个名为 this_shell.sh 的脚本中),请将输出发送到控制台以查看发生了什么,然后在每个上使用sed找到的文件名用文本替换文本foo:

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结果只允许查看带有目标文本的文件(因此也可能提高性能/速度)

务必备份您的文件&amp;使用前测试。对于具有嵌入空格的文件,可能无法在某些环境中使用(?)

答案 6 :(得分:0)

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

/pattern/s/xx/yy/g

然后你想把I放在模式之后:

/pattern/Is/xx/yy/g

示例:

echo Fred | sed '/fred/Is//willma/g'

返回willma;如果没有I,则返回未触及的字符串(Fred)。

答案 7 :(得分:0)

使用以下命令替换所有出现的内容: sed的s / foo / bar / gI mylog.txt

答案 8 :(得分:-2)

sed 's/string1/string2/Ig'

Capital I是一个选项,对于搜索字符串非常有用,无论区分大小写。