我试图匹配包含两个文本模式的文件名,但是匹配过程应该忽略大小写。以下两个正则表达式都不起作用:
将awk变量'IGNORECASE‘设置为非零值(如info awk
中所建议的),以便所有正则表达式和字符串操作忽略大小写,然后使用两个正则表达式构建逻辑“和”操作输出所有文件:
$ 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
匹配的字符串常量“宾果”,似乎D8
可能正在对ls -R
输出中的每个文件中的行执行匹配。如果是这样的话,在接收来自(即通过)管道的输出时,如何使awk
具有与grep
相同的行为?
发布于 2019-08-04 21:46:03
wrt您的第一个脚本:
awk 'IGNORECASE = 1;/bingo/ && /number/;'
因此,它将在GNU awk中执行不区分大小写的匹配,但在其他awk中不进行匹配,并且它将始终打印当前行(因为赋值IGNORECASE=1
计算为1
,这是一个真正的条件),然后包含宾果和数字的任何行都将再次打印。
wrt您的第二个脚本:
awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'
?=
的东西是PCRE的看点-- awk支持ERE,而不是PCREs,所以我必须考虑一下它在ERE中的真正含义,但不管它是什么,这不是你想要它的意思。
wrt您的声明:
看起来awk可能是针对ls -R输出中每个文件中的行执行匹配的。
我不知道你为什么这么想,但不,不是。
我认为你在GNU awk中想要的是:
awk 'BEGIN{IGNORECASE=1}; /bingo/ && /number/'
或者:
awk -v IGNORECASE=1 '/bingo/ && /number/'
在任何情况下:
awk '{lc=tolower($0)}; (lc ~ /bingo/) && (lc ~ /number/)'
发布于 2019-08-05 07:03:22
如果您想在当前目录或在任何情况下都包含字符串bingo
和number
的目录中找到名称,则不应该通过awk
传递ls -R
的输出,而应该使用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*'
和find
,而不是使用两个-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
或者,如果您有GNU basename
,并且不希望任何时候匹配数千个文件,
shopt -s globstar nocaseglob failglob
basename -a -- **/*bingo*number*
其中,-a
告诉实用程序显示每个参数的文件名部分(多个参数)。
Stéphane在注释中指出,要忽略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
相关信息:
https://unix.stackexchange.com/questions/533848
复制相似问题