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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4412945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 07:25:51  来源:igfitidea点击:

Case-insensitive search and replace with sed

macosreplacesedcase-insensitive

提问by Craig Walker

I'm trying to use SED to extract text from a log file. I can do a search-and-replace without too much trouble:

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

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

However, I want to make the search case-insensitive. From what I've googled, it looks like appending ito the end of the command should work:

但是,我想让搜索不区分大小写。从我用谷歌搜索的内容来看,似乎附加i到命令的末尾应该有效:

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

However, this gives me an error message:

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

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

What's going wrong here, and how do I fix it?

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

采纳答案by mklement0

To be clear: On macOS- as of Mojave (10.14) - sed- which is the BSDimplementation - does NOT support case-insensitive matching- hard to believe, but true. The formerly accepted answer, which itself shows a GNUsedcommand, gained that status because of the perl-based solution mentioned in the comments.

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

To make that Perl solutionwork with foreign charactersas well, via UTF-8, use something like:

要使Perl 解决方案也适用于外来字符,请通过 UTF-8,使用以下内容:

perl -C -Mutf8 -pe 's/??/oo/i' <<< "F??" # -> "Foo"
  • -Cturns on UTF-8 support for streams and files, assuming the current locale is UTF-8-based.
  • -Mutf8tells Perl to interpret the source codeas UTF-8 (in this case, the string passed to -pe) - this is the shorter equivalent of the more verbose -e 'use utf8;'.Thanks, Mark Reed
  • -C打开对流和文件的 UTF-8 支持,假设当前语言环境是基于 UTF-8 的。
  • -Mutf8告诉 Perl 将源代码解释为 UTF-8(在这种情况下,传递给 的字符串-pe) - 这是更冗长的较短等价物-e 'use utf8;'.谢谢,马克里德

(Note that using awkis not an option either, as awkon macOS (i.e., BWK awk, a.k.a. BSD awk) appears to be completely unaware of locales altogether - its tolower()and toupper()functions ignore foreign characters (and sub()/ gsub()don't have case-insensitivity flags to begin with).)

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

回答by Wesley Rice

Editor's note: This solution doesn't work on macOS (out of the box), because it only applies to GNUsed, whereas macOS comes with BSDsed.

编者注:此解决方案不适用于 macOS(开箱即用),因为它仅适用于GNUsed,而 macOS 带有BSDsed

Capitalize the 'I'.

大写“我”。

sed 's/foo/bar/I' file

回答by Wesley Rice

Another work-around for sedon Mac OS X is to install gsedfrom MacPorts or HomeBrew and then create the alias sed='gsed'.

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

回答by Benjamin W.

The sed FAQaddresses the closely related case-insensitive search. It points out that a) many versions of sed support a flag for it and b) it's awkward to do in sed, you should rather use awk or Perl.

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

But to do it in POSIX sed, they suggest three options (adapted for substitution here):

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

  1. Convert to uppercase and store original line in hold space; this won't work for substitutions, though, as the original content will be restored before printing, so it's only good for insert or adding lines based on a case-insensitive match.

  2. Maybe the possibilities are limited to FOO, Fooand foo. These can be covered by

    s/FOO/bar/;s/[Ff]oo/bar/
    
  3. To search for all possible matches, one can use bracket expressions for each character:

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

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

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

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

回答by user1307434

The Mac version of sedseems a bit limited. One way to work around this is to use a linux container (via Docker) which has a useable version of sed:

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

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

回答by gojimmypi

I had a similar need, and came up with this:

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

this command to simply find all the files:

这个命令可以简单地找到所有文件:

grep -i -l -r foo ./* 

this one to exclude this_shell.sh (in case you put the command in a script called this_shell.sh), tee the output to the console to see what happened, and then use sed on each file name found to replace the text foo with bar:

this 排除 this_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 

I chose this method, as I didn't like having all the timestamps changed for files not modified. feeding the grep result allows only the files with target text to be looked at (thus likely may improve performance / speed as well)

我选择了这种方法,因为我不喜欢为未修改的文件更改所有时间戳。提供 grep 结果只允许查看带有目标文本的文件(因此也可能提高性能/速度)

be sure to backup your files & test before using. May not work in some environments for files with embedded spaces. (?)

请务必在使用前备份您的文件并进行测试。对于带有嵌入空格的文件,在某些环境中可能不起作用。(?)

回答by CBB

If you are doing pattern matching first, e.g.,

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

/pattern/s/xx/yy/g

then you want to put the Iafter the pattern:

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

/pattern/Is/xx/yy/g

Example:

例子:

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

returns willma; without the I, it returns the string untouched (Fred).

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