# Case-insensitive search in awk

I need to search for a keyword using awk, but I want to perform a case-insensitive (non case sensitive) search.

I think the best approach is to capitalize both the search term ("key word") and the target line that awk is reading at the same time. From this question I how to use toupper to print in all uppercase, but I don't know how to use it in a match because that answer just shows printing and doesn't leave the uppercase text in a variable.

Here is an example, given this input:

blablabla
&&&Key Word&&&
I want all
these text and numbers 123
and chars !"£$%& as output &&&KEY WORD&&& blablabla  I'd like this output: I want all these text and numbers 123 and chars !"£$%&
as output


This is what I have, but I don't know how to add in toupper:

awk "BEGIN {p=0}; /&&&key word&&&/ { p = ! p ; next } ; p { print }" text.txt


Replace your expression to match a pattern (i.e. /&&&key word&&&/) by another expression explicitly using $0, the current line: tolower($0) ~ /&&&key word&&&/


or

toupper($0) ~ /&&&KEY WORD&&&/  so you have awk 'tolower($0) ~ /&&&key word&&&/ { p = ! p ; next }; p' text.txt


You need single quotes because of the $0, the BEGIN block can be removed as variables are initialised by default to "" or 0 on first use, and {print} is the default action, as mentioned in the comments below. • Note that you could simplify that to awk 'toupper($0)~/&&&KEY WORD&&&/ { p = ! p ; next } ; p;' text.txt. There's no need for the BEGIN block and since the default action is to print, p; is enough. – terdon Apr 1 '16 at 12:35
• "There's no need for the BEGIN block" since an uninitialized variable evaluates as false. – glenn jackman Apr 1 '16 at 13:44
• Thanks for the optimisations. I usually try to limit my reply to minimal changes to the original, but it's true the new result is much tighter and quite readable. – meuh Apr 1 '16 at 14:06
• Just a note: tolower is present on ancient (or not so ancient) awk versions (ex: AIX) systems, but toupper is not always available ^^. – Olivier Dulac Apr 1 '16 at 20:20

gawk has an IGNORECASE builtin variable, which, if set to nonzero, causes all string and regular expression comparisons to be case-insensitive. You could use that:

BEGIN{IGNORECASE=1}
/&&&key word&&&/ { foo bar baz }


etc. This is specific to gawk, though, but I find it to be more readable than the (more portable) alternative by meuh. Whether that's a problem is, of course, fully up to you.

• I've wanted to support awk for years in one of my biggest gawk projects, but the lack of case insensitive search triggers that gawk has made it a non starter due to the number of case insensitive searches the stuff runs. gensub is the other gawk only feature that was too hard to replace in awk. But gawk isn't always installed by default on some machines and distributions, though it's almost always available, but it's unfortunate that by 2016 they couldn't change awk and posix to expand the functionality of such standard tools a bit. – Lizardx Apr 1 '16 at 19:30
• @Lizardx: that's the whole point of not expanding: keep it standard. Otherwise you just create another standard, and then you have some incompabilities between them (they do that, but try to keep the standard changes to a minimum ... even then, multiple standard is one of the main plagues of computing) – Olivier Dulac Apr 1 '16 at 20:22
• I don't agree. With careful execution, you can introduce expansions while supporting all legacy methods, what happens if you fail to do that is the stuff just starts to fade away into irrelevance over time. Everything in computing evolves, the trick is to maintain a very stable reliable evolution. Bash is a good example of doing that, super reliable and simply add new features, it's not 'two standards' so much as, use what is supported, and once the changes have rolled out globally you can start using the new features because only the oldest legacy systems won't have support. – Lizardx Apr 1 '16 at 20:46