首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在awk正则表达式中操作和大小写不敏感?

在awk正则表达式中操作和大小写不敏感?
EN

Unix & Linux用户
提问于 2019-08-04 18:10:48
回答 2查看 1.5K关注 0票数 0

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

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

代码语言:javascript
运行
复制
$ ls -R | awk 'IGNORECASE = 1;/bingo/ && /number/;'

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

代码语言:javascript
运行
复制
$ ls -R | awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

awk或正则表达式语法的哪一部分是错误的(或缺少什么),以及只有当附加模式出现在同一行时才能成功地执行独立于案例的搜索的正确方法是什么?

更新:

不跑

代码语言:javascript
运行
复制
$ ls -R | awk '/bingo/'

由于文件名不包含由awk匹配的字符串常量“宾果”,似乎D8可能正在对ls -R输出中的每个文件中的行执行匹配。如果是这样的话,在接收来自(即通过)管道的输出时,如何使awk具有与grep相同的行为?

EN

回答 2

Unix & Linux用户

发布于 2019-08-04 21:46:03

wrt您的第一个脚本:

代码语言:javascript
运行
复制
awk 'IGNORECASE = 1;/bingo/ && /number/;'
  1. IGNORECASE是gawk-正如评论中指出的那样,并且
  2. 您的awk代码等效于: awk '(IGNORECASE = 1){print};(/bingo/ &number/){print}‘

因此,它将在GNU awk中执行不区分大小写的匹配,但在其他awk中不进行匹配,并且它将始终打印当前行(因为赋值IGNORECASE=1计算为1,这是一个真正的条件),然后包含宾果和数字的任何行都将再次打印。

wrt您的第二个脚本:

代码语言:javascript
运行
复制
awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

?=的东西是PCRE的看点-- awk支持ERE,而不是PCREs,所以我必须考虑一下它在ERE中的真正含义,但不管它是什么,这不是你想要它的意思。

wrt您的声明:

看起来awk可能是针对ls -R输出中每个文件中的行执行匹配的。

我不知道你为什么这么想,但不,不是。

我认为你在GNU awk中想要的是:

代码语言:javascript
运行
复制
awk 'BEGIN{IGNORECASE=1}; /bingo/ && /number/'

或者:

代码语言:javascript
运行
复制
awk -v IGNORECASE=1 '/bingo/ && /number/'

在任何情况下:

代码语言:javascript
运行
复制
awk '{lc=tolower($0)}; (lc ~ /bingo/) && (lc ~ /number/)'
票数 5
EN

Unix & Linux用户

发布于 2019-08-05 07:03:22

如果您想在当前目录或在任何情况下都包含字符串bingonumber的目录中找到名称,则不应该通过awk传递ls -R的输出,而应该使用find

代码语言:javascript
运行
复制
find . -iname '*bingo*' -iname '*number*'

-iname谓词是非标准的,但通常是实现的,并且将匹配当前正在根据给定的全局模式进行检查的文件名。

如果您希望只获取文件名,而不是找到的文件的完整路径名,则请使用

代码语言:javascript
运行
复制
find . -iname '*bingo*' -iname '*number*' -exec basename {} \;

使用GNU find,您可以使用

代码语言:javascript
运行
复制
find . -iname '*bingo*' -iname '*number*' -printf '%f\n'

这将比使用basename更快。

如果您知道这两个单词的顺序是"bingo后面跟着number",那么使用-iname '*bingo*number*'find,而不是使用两个-iname测试。

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

代码语言:javascript
运行
复制
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*

要获取路径名的文件名部分,请执行以下操作:

代码语言:javascript
运行
复制
shopt -s globstar nocaseglob failglob

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

或者,如果您有GNU basename,并且不希望任何时候匹配数千个文件,

代码语言:javascript
运行
复制
shopt -s globstar nocaseglob failglob

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

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

Stéphane在注释中指出,要忽略bash中两个子字符串的顺序,可以使用扩展的全局模式

代码语言:javascript
运行
复制
!(!(*bingo*)|!(*number*))

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

代码语言:javascript
运行
复制
shopt -s globstar nocaseglob failglob
shopt -s extglob  # for extended globbing patterns in bash

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

相关信息:

票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/533848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档