awk中不区分大小写的字符串匹配

Case insensitive string matching in awk

假设一个多行文本文件 file 其中一些行以空格开头。

$ cat file
foo Baz
  baz QUX
    QUx Quux
BaZ Qux
BazaaR

进一步假设我希望将所有以关键字开头的行(例如“baz”)转换为小写字母,而不管 (a) 该关键字是否写在小写或大写字母(或其任意组合)本身,以及 (b) 该关键字前面有空格。

$ cat file | sought_command
foo Baz        # not to lowercase (line does not start with keyword)
  baz qux      # to lowercase
    QUx Quux
baz qux        # to lowercase
BazaaR         # not to lowercase (line does not start with keyword, but merely with a word containing the keyword)

我相信 awk 是实现它的工具,但我不确定如何实现关键字匹配的不区分大小写。

$ cat file | awk '{ if( ~ /^ *baz/) print tolower([=12=]); else print [=12=]}'
foo Baz
  baz qux
    QUx Quux
BaZ Qux       # ERROR HERE: was not replaced, b/c keyword not recognized.
BazaaR

编辑 1: 添加 IGNORECASE=1 似乎解决了不区分大小写的问题,但现在错误地将最后一行转换为小写。

$ cat file | awk '{IGNORECASE=1; if(~/^ *baz/) print tolower([=13=]); else print [=13=]}'
foo Baz
  baz qux
    QUx Quux
baz qux
bazaar       # ERROR HERE: should not be converted to lowercase, as keyword not present (emphasis on word!).

在搜索字符串后添加单词边界

$ awk '{IGNORECASE=1; if(~/^ *baz\>/) print tolower([=10=]); else print [=10=]}' ip.txt 
foo Baz
  baz qux
    QUx Quux
baz qux
BazaaR

可以重写为:

awk 'BEGIN{IGNORECASE=1} /^ *baz\>/{[=11=]=tolower([=11=])} 1' ip.txt 

由于使用了line anchor,所以不需要匹配</code>。最后的 <code>1 将打印记录,包括所做的任何更改

IGNORECASE\>gawk 特定功能。 \y也可以用来匹配单词边界


随着 GNU sed

$ sed 's/^[[:blank:]]*baz\b.*/\L&/I' ip.txt 
foo Baz
  baz qux
    QUx Quux
baz qux
BazaaR
  • [[:blank:]] 将匹配 space 或制表符
  • \L& 会将行
  • 小写
  • \b是单词边界
  • I 不区分大小写匹配的标志

您已经知道 tolower() 所以只需在比较中再次使用它并测试精确的字符串匹配而不是部分正则表达式:

awk 'tolower()=="baz"{[=10=]=tolower([=10=])}1'