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

Mic*_*udl 4 string awk case-sensitive lowercase matching

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

$ cat file
foo Baz
  baz QUX
    QUx Quux
BaZ Qux
BazaaR
Run Code Online (Sandbox Code Playgroud)

进一步假设我希望将所有以关键字(例如“ 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)
Run Code Online (Sandbox Code Playgroud)

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

$ cat file | awk '{ if($1 ~ /^ *baz/) print tolower($0); else print $0}'
foo Baz
  baz qux
    QUx Quux
BaZ Qux       # ERROR HERE: was not replaced, b/c keyword not recognized.
BazaaR
Run Code Online (Sandbox Code Playgroud)

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

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

Sun*_*eep 8

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

$ awk '{IGNORECASE=1; if($1~/^ *baz\>/) print tolower($0); else print $0}' ip.txt 
foo Baz
  baz qux
    QUx Quux
baz qux
BazaaR
Run Code Online (Sandbox Code Playgroud)

可以重写为:

awk 'BEGIN{IGNORECASE=1} /^ *baz\>/{$0=tolower($0)} 1' ip.txt 
Run Code Online (Sandbox Code Playgroud)

由于使用了线锚,因此无需与 匹配$1。最后1将打印记录,包括所做的任何更改

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


GNU sed

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


Ed *_*ton 7

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

awk 'tolower($1)=="baz"{$0=tolower($0)}1'
Run Code Online (Sandbox Code Playgroud)