Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case-insensitive search and replace with sed

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 's/foo/bar/' mylog.txt 

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

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?

like image 510
Craig Walker Avatar asked Dec 10 '10 20:12

Craig Walker


People also ask

Which I command is used for case insensitivity in sed command?

GNU sed and other version does support a case-insensitive search using I flag after /regex/.

How do you make a case-insensitive in Unix?

The key to that case-insensitive search is the use of the -iname option, which is only one character different from the -name option. The -iname option is what makes the search case-insensitive.

How do you grep a case-insensitive?

Case Insensitive Search By default, grep is case sensitive. This means that the uppercase and lowercase characters are treated as distinct. To ignore case when searching, invoke grep with the -i option (or --ignore-case ).


2 Answers

Update: Starting with macOS Big Sur (11.0), sed now does support the I flag for case-insensitive matching, so the command in the question should now work (BSD sed doesn't reporting its version, but you can go by the date at the bottom of the man page, which should be March 27, 2017 or more recent); a simple example:

# BSD sed on macOS Big Sur and above (and GNU sed, the default on Linux) $ sed 's/ö/@/I' <<<'FÖO' F@O   # `I` matched the uppercase Ö correctly against its lowercase counterpart 

Note: I (uppercase) is the documented form of the flag, but i works as well.

Similarly, starting with macOS Big Sur (11.0) awk now is locale-aware (awk --version should report 20200816 or more recent):

# BSD awk on macOS Big Sur and above (and GNU awk, the default on Linux) $ awk 'tolower($0)' <<<'FÖO' föo  # non-ASCII character Ö was properly lowercased 

The following applies to macOS up to Catalina (10.15):

To be clear: On macOS, sed - which is the BSD implementation - does NOT support case-insensitive matching - hard to believe, but true. The formerly accepted answer, which itself shows a GNU sed command, gained that status because of the perl-based solution mentioned in the comments.

To make that Perl solution work with foreign characters as well, via UTF-8, use something like:

perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo" 
  • -C turns on UTF-8 support for streams and files, assuming the current locale is UTF-8-based.
  • -Mutf8 tells Perl to interpret the source code as 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

(Note that using awk is not an option either, as awk on macOS (i.e., BWK awk and 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).)


A note on the relationship of sed and awk to the POSIX standard:

BSD sed and awk limit their functionality mostly to what the POSIX sed and POSIX awk specs mandate, whereas their GNU counterparts implement many more extensions.

like image 107
mklement0 Avatar answered Oct 13 '22 12:10

mklement0


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

Capitalize the 'I'.

sed 's/foo/bar/I' file 
like image 20
Wesley Rice Avatar answered Oct 13 '22 11:10

Wesley Rice