我正在尝试匹配包含两个文本模式的文件名,但匹配过程应忽略大小写。以下正则表达式都不起作用:
将 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/;'
- 正如评论中指出的那样,IGNORECASE 仅限于呆呆,并且
你的 awk 代码相当于:
awk '(IGNORECASE = 1){print}; (/bingo/ && /number/){print}'
因此它将在 GNU awk 中进行不区分大小写的匹配,但在其他 awks 中则不会,并且它将始终打印当前行(因为赋值IGNORECASE=1
评估为1
true 条件),然后将打印包含 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 -R
awk
find
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
有关的: