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

10
假设有一个多行文本文件file,其中一些行以空格开头。
$ cat file
foo Baz
  baz QUX
    QUx Quux
BaZ Qux
BazaaR

进一步假设我希望将所有以关键字开头的行(例如"baz")转换为小写字母,无论该关键字本身是以小写或大写字母(或任何组合)书写的,以及该关键字是否在空格前面。

$ 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($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

编辑 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!).

1
我不知道awk是否支持大小写不敏感匹配(像其他一些正则表达式方言一样)。但是这应该可以工作:/^ *[bB][aA][zZ]/ - Scheff's Cat
2个回答

10

您已了解 tolower(),因此可以再次在比较中使用它,并测试是否完全匹配字符串,而不是部分正则表达式:

awk 'tolower($1)=="baz"{$0=tolower($0)}1'

8
在搜索字符串后添加单词边界。
$ awk '{IGNORECASE=1; if($1~/^ *baz\>/) print tolower($0); else print $0}' ip.txt 
foo Baz
  baz qux
    QUx Quux
baz qux
BazaaR

可以重写为:

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

由于使用了行锚定(line anchor),无需与$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
  • [[:blank:]]将匹配空格或制表符
  • \L&会将行转换为小写
  • \b是单词边界
  • I标志用于不区分大小写的匹配

1
我印象深刻(尤其是关于IGNORECASE)。关于你的awk示例:\>是单词边界吗? - Scheff's Cat
实际上,OP在编辑中提到了IGNORECASE... \>匹配单词的结束位置。 - Sundeep
他的编辑出现在你的回答的同一分钟。因此,我不确定应该把我的印象指向哪里。你因为\>而获胜... - Scheff's Cat
@Sundeep 感谢您详细的回答。关于您的 awk 解决方案,我有一个后续问题:如果(且仅当)行以分号结尾,如何强制转换为小写字母进行关键字匹配。例如:BaZ Qux; 转换为 baz qux;,而 BaZ Qux 则不会。 - Michael Gruenstaeudl
@MichaelGruenstaeudl 你可以逻辑地组合条件... 所以 /^ *baz\>/ && /;$/.. - Sundeep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接