awk 正则表达式中的运算和大小写不敏感?

awk 正则表达式中的运算和大小写不敏感?

我正在尝试匹配包含两个文本模式的文件名,但匹配过程应忽略大小写。以下正则表达式都不起作用:

将 awk 变量 'IGNORECASE' 设置为非零值(按照 中的建议info awk),以便所有正则表达式和字符串操作忽略大小写,然后使用两个正则表达式构建逻辑“and”操作打印所有文件:

$ ls -R | awk 'IGNORECASE = 1;/bingo/ && /number/;'


我尝试在使用前瞻(我知道不需要第二次前瞻)之前将数据转换为小写,以匹配文本模式“bingo”和“number”。但是 awk 不会打印默认情况下应该打印的任何输出1,2

$ ls -R | awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

awk 或正则表达式语法的哪一部分是错误的(或缺少什么),以及执行与大小写无关的搜索的正确方法是什么,该搜索仅当附加模式出现​​在同一行时才会成功?

更新:

从跑步

$ ls -R | awk '/bingo/'

似乎awk可能正在对输出中每个文件中的行执行匹配,因为ls -R文件名不包含与 . 匹配的字符串常量“bingo” awk。如果是这种情况,如何获得与从管道接收输出(即通过管道发送)时awk相同的行为?grep

答案1

写下你的第一个脚本:

awk 'IGNORECASE = 1;/bingo/ && /number/;'
  1. 正如评论中指出的那样,IGNORECASE 仅限于呆呆,并且
  2. 你的 awk 代码相当于:

    awk '(IGNORECASE = 1){print}; (/bingo/ && /number/){print}'
    

因此它将在 GNU awk 中进行不区分大小写的匹配,但在其他 awks 中则不会,并且它将始终打印当前行(因为赋值IGNORECASE=1评估为1true 条件),然后将打印包含 bingo 和 number 的任何行第二次。

写你的第二个脚本:

awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

?=东西是 PCRE 环视 - awk 支持 ERE,而不是 PCRE,所以我必须考虑它在 ERE 中的真正含义,但无论它是什么,它都不是您想要的含义。

你的陈述是:

看来 awk 可能正在对 ls -R 的输出中每个文件中的行执行匹配

我不知道你为什么这么想,但不,事实并非如此。

我想这就是你在 GNU awk 中想要的:

awk 'BEGIN{IGNORECASE=1}; /bingo/ && /number/'

或者:

awk -v IGNORECASE=1 '/bingo/ && /number/'

在任何 awk 中:

awk '{lc=tolower($0)}; (lc ~ /bingo/) && (lc ~ /number/)'

答案2

如果您想在当前目录或包含字符串的目录下查找名称bingo,并且在任何情况下,您不应传递throughnumber的输出,而应使用:ls -Rawkfind

find . -iname '*bingo*' -iname '*number*'

-iname谓词是非标准的,但通常实现,并且将根据给定的通配模式匹配当前正在检查的文件名,不区分大小写。

如果你想获取文件名仅有的,而不是找到的文件的完整路径名,然后使用

find . -iname '*bingo*' -iname '*number*' -exec basename {} \;

使用 GNU find,您可以使用

find . -iname '*bingo*' -iname '*number*' -printf '%f\n'

这会比使用更快basename

如果你知道这两个单词的顺序是“bingo后跟number”,那么就用-iname '*bingo*number*'withfind代替两个-iname测试。

如果您知道这是您要查找的单词的顺序,您也可以bash直接使用:

shopt -s globstar      # enable ** to match across / in pathnames
shopt -s nocaseglob    # enable case-insensitive globbing
shopt -s failglob      # error when a pattern does not match anything

printf '%s\n' **/*bingo*number*

要获取路径名的文件名部分:

shopt -s globstar nocaseglob failglob

for name in **/*bingo*number*; do
    basename -- "$name"
done

或者,如果您有 GNUbasename并且不希望匹配数千文件数,

shopt -s globstar nocaseglob failglob

basename -a -- **/*bingo*number*

where-a告诉实用程序显示每个参数(多个参数)的文件名部分。

Stéphane 在评论中指出,要忽略 eg 中两个子字符串的顺序bash,您可以使用扩展的通配模式

!(!(*bingo*)|!(*number*))

这是通过匹配除以下名称之外的每个名称来实现的:不要包含两个字符串之一。所以你会得到

shopt -s globstar nocaseglob failglob
shopt -s extglob  # for extended globbing patterns in bash

for name in **/!(!(*bingo*)|!(*number*)); do
    basename -- "$name"
done

有关的:

相关内容