无忧启动论坛

标题: 请教一个正则表达式该如何写?(已解决) [打印本页]

作者: likeyouli    时间: 昨天 09:07
标题: 请教一个正则表达式该如何写?(已解决)
本帖最后由 likeyouli 于 2024-9-27 16:29 编辑

  以解决,谢谢7楼。
待搜索内容:
zlib-1.2.7-18.el7.x86_64.gpm
zlib-devel-1.2.7-18.el7.i686.rpm
zlib-devel-1.2.7-18.el7.x86_64.rpm
zlib-static-1.2.7-18.el7.i686.rpm
zlib-static-1.2.7-18.el7.x86_64.rpm
zsh-5.0.2-34.el7_8.2.x86_64.rdm
zsh-html-5.0.2-34.el7_8.2.x86_64.rpg
zziplib-0.13.62-12.el7.i686.rpm
zziplib-0.13.62-12.el7.x86_64.rpm
zziplib-devel-0.13.62-12.el7.i686.rpm
zziplib-devel-0.13.62-12.el7.x86_64.rpm
zziplib-utils-0.13.62-12.el7.x86_64.rpm

   匹配以 “.rpm” 结尾的除了“.rpm”之外的内容,如:zziplib-devel-0.13.62-12.el7.i686.rpm,我只想匹配出 zziplib-devel-0.13.62-12.el7.i686
    不知道这个正则表达式该怎样写 ?  百度搜索出来的,请先测试后再回帖,因为我也百度了好多次,测试后发现都不行。
     7楼的可以:.*(?=\.rpm$)    (?=xxx) 表示在xxx前边
——————————————————————————————————————————————————————————————————————————————————————————————————————————————
  以上为原题,升级为以下题目,centos系统(iso镜像)挂载后(顺便说一下挂载命令①mkdir /likeyou,根目录下创建likeyou文件夹;②mount /dev/cdrom /likeyou 提示:mount: /dev/sr0 写保护,将以只读方式挂载。重新进入likeyou文件夹即可看到挂载的文件。),打开Packages文件夹,ls,会看到以下类似包:
yum-plugin-versionlock-1.1.31-54.el7_8.noarch.rpm
yum-rhn-plugin-2.0.1-10.el7.noarch.rpm
yum-updateonboot-1.1.31-54.el7_8.noarch.rpm
yum-utils-1.1.31-54.el7_8.noarch.rpm
zenity-3.28.1-1.el7.x86_64.rpm
zip-3.0-11.el7.x86_64.rpm
zlib-1.2.7-18.el7.i686.rpm
zlib-1.2.7-18.el7.x86_64.rpm
zlib-devel-1.2.7-18.el7.i686.rpm
zlib-devel-1.2.7-18.el7.x86_64.rpm
zlib-static-1.2.7-18.el7.i686.rpm
zlib-static-1.2.7-18.el7.x86_64.rpm
zsh-5.0.2-34.el7_8.2.x86_64.rpm
zsh-html-5.0.2-34.el7_8.2.x86_64.rpm
zziplib-0.13.62-12.el7.i686.rpm
zziplib-0.13.62-12.el7.x86_64.rpm
zziplib-devel-0.13.62-12.el7.i686.rpm
zziplib-devel-0.13.62-12.el7.x86_64.rpm
zziplib-utils-0.13.62-12.el7.x86_64.rpm
  要求:提取每行中以.rpm结尾、倒数第一个.与倒数第二个点之间的内容,也就是类似x86_64、i686、noarch这样的内容,这些其实代表的是这个包支持的架构。
我发现提取的方式多种多样,比如用cut、rev,awk,有些还得配合正则表达式才能完成,但仅用一个表达式就能提取出来的只有正则表达式:
   ls|grep -Po '[^\.]+(?=\.rpm$)'   然后就可以|sort|uniq -c  排序、去重并统计重复个数。

     正则表达式魅力无限啊
         又想到一个题目:不管最后一个.后边是不是rpm,我就要求取倒数第一个.与倒数第二个.之间的内容,也就是类似x86_64、i686、noarch这样的内容,可以这样写:  ls|grep -Po '[^.]+(?=\.[^.]+$)'     , 多次测试,发现[ ] 这里边无论写. 还是写\. 好像都行,难道中括号里边的. 就是点,而不是元字符?经过测试发现,反选时中括号里边[^.] 与 [^\.] 表示的意思一样,都是表示除了点之外的内容。______________________________________________________________________________________________
继续发散:如果要取倒数第二个点与倒数第三个点之间的内容呢 ?也就是el7,那就可以这样写:
ls|grep -P '[^.]+(?=\.[^.]+\.[^.]+$)'      ,正则表达式实在太灵活了,有了它,还要什么awk啊, 据说awk取列还相当复杂,除了awk取的列能直接运算、能重新排列,除此之外,单纯提取内容相对于正则表达式就是渣。




作者: scq330    时间: 昨天 09:39
文心一言的回答,供你参考:
要匹配以“.rpm”结尾的字符串,但只保留到“.rpm”之前的部分,你可以使用正则表达式中的“捕获组”功能,并结合“非贪婪匹配”来确保只匹配到最后一个“.rpm”之前的所有内容。但是,由于你实际上是在使用正则表达式来提取信息,而不是进行简单的匹配,因此你需要使用支持捕获组功能的工具或编程语言。

在大多数正则表达式引擎中,你可以使用以下模式:

regex
^(.*?)\.rpm$
这里的^表示字符串的开始,(.*?)是一个非贪婪的捕获组,它会匹配尽可能少的字符,直到遇到后面的模式(这里是.rpm),.rpm直接匹配文本“.rpm”,$表示字符串的结束。

但是,请注意,这个正则表达式假设整个字符串就是你想要匹配的那一行,即每行只有一个以“.rpm”结尾的字符串。如果你的环境(如某些文本编辑器或编程语言)支持这种正则表达式,并且你正在逐行处理这些字符串,那么这个正则表达式就能工作得很好。

然而,如果你是在一个不支持直接提取捕获组内容的简单文本搜索环境中(比如某些简单的文本编辑器或命令行工具),你可能需要采用其他方法,比如使用支持正则表达式的命令行工具(如grep配合sed或awk)来提取这些信息。

例如,在bash中使用grep和sed组合来提取每行中“.rpm”之前的部分:

bash
grep -oP '^(.*?)\.rpm$' yourfile.txt | sed 's/\.rpm$//'
这里,grep -oP选项允许你使用Perl兼容的正则表达式(PCRE),并只输出匹配的部分。sed 's/\.rpm$//'用于移除每行末尾的“.rpm”。但是,请注意,由于你的示例中每行只有一个以“.rpm”结尾的字符串,这个命令实际上会按行输出每个匹配项(即每行一个结果),并且已经移除了“.rpm”后缀。

如果你的环境或工具不支持这些选项,你可能需要查找特定于该环境的解决方案。
作者: zlq_hysy    时间: 昨天 09:47
对于单行,^(.*?)\.rpm$。多行怎么弄?
作者: likeyouli    时间: 昨天 09:47
scq330 发表于 2024-9-27 09:39
文心一言的回答,供你参考:
要匹配以“.rpm”结尾的字符串,但只保留到“.rpm”之前的部分,你可以使用正 ...

你是用的 sed 's/\.rpm$//'  算是绕道,不是仅用正则表达式。
作者: likeyouli    时间: 昨天 09:51
zlq_hysy 发表于 2024-9-27 09:47
对于单行,^(.*?)\.rpm$。多行怎么弄?

看准题,不要匹配出 .rpm
作者: zlq_hysy    时间: 昨天 09:59
本帖最后由 zlq_hysy 于 2024-9-27 10:41 编辑
likeyouli 发表于 2024-9-27 09:51
看准题,不要匹配出 .rpm

没错呀,匹配 .rpm前面的。
au3写的代码:


作者: Jcz777    时间: 昨天 10:11
加一个非捕获组。
  1. .*(?=\.rpm$)
复制代码

作者: szwp    时间: 昨天 10:12
grep -oP .+(?=.rpm$) t.txt
批处理的for更方便,不需要第三方软件
作者: tt911    时间: 昨天 10:20
前面说
匹配以 “.rpm” 结尾

后面又说
除了“.rpm”之外的内容

最后结果却是:
zziplib-devel-0.13.62-12.el7.i686

反正我脑袋大了。感觉前后矛盾啊。
作者: likeyouli    时间: 昨天 10:28
本帖最后由 likeyouli 于 2024-9-27 10:38 编辑
tt911 发表于 2024-9-27 10:20
前面说

后面又说

表述错了吗 ?
匹配以 “.rpm” 结尾 ,意思是查找的每行内容中必须以 .rpm结尾,看搜索内容,有的行不以.rpm结尾,这样的行首先排除了;
除了“.rpm”之外的内容,我又不想要.rpm 这几个字,,嗯,之外这两个字多余,每行中除了“.rpm”后剩余的内容
  两个条件,不矛盾啊
作者: likeyouli    时间: 昨天 10:36
szwp 发表于 2024-9-27 10:12
grep -oP .+(?=.rpm$) t.txt
批处理的for更方便,不需要第三方软件

谢谢,如果用excel更方便,left len函数一嵌套就行,
grep -oP .+(?=.rpm$)     .前边必须要用\转义吧,否则仅代表一个字符, 如果有zziplib-devel-0.13.62-12.el7.i686rpm 就会匹配出zziplib-devel-0.13.62-12.el7.i68,但这行是不符合.rpm结尾要求的。
作者: zlq_hysy    时间: 昨天 10:36
tt911 发表于 2024-9-27 10:20
前面说

后面又说

意思是:找到以“.rpm”结尾的行,然后删除‘.rpm’,取剩余的字串
作者: szwp    时间: 昨天 10:44
likeyouli 发表于 2024-9-27 10:36
谢谢,如果用excel更方便,left len函数一嵌套就行,
grep -oP .+(?=.rpm$)     .前边必须要用\转义吧, ...

如果直接针对某一目录的,就不需要先生成文件列表了。多试试总会成功的。
作者: likeyouli    时间: 昨天 10:46
zlq_hysy 发表于 2024-9-27 09:59
没错呀,匹配 .rpm前面的。
au3写的代码:

你这貌似用()分的组,
然后取的【0】,也就是第一组,所以看似匹配成功了,但仅从正则表达式来看,也把.rpm匹配出来了。
作者: zlq_hysy    时间: 昨天 11:07
likeyouli 发表于 2024-9-27 10:46
你这貌似用()分的组,
然后取的【0】,也就是第一组,所以看似匹配成功了,但仅从正则表达式来看,也 ...

是的老大,例子只是一个单一的字串的捕获,第二句的au3函数返回的是一个只有一个元素的数组。
作者: ldg_2    时间: 昨天 11:09
需要用到正则表达式的顺序环视
作者: wang1126    时间: 昨天 13:12
谢谢7楼分享
作者: guong    时间: 昨天 13:32
来了解下
作者: tt911    时间: 昨天 13:42
要是我的话,我直接用前瞻引用了。
书中太高级的部分,没整明白。
学习了。
作者: yzqmxh    时间: 昨天 14:21
学习了




欢迎光临 无忧启动论坛 (http://bbs.wuyou.net./) Powered by Discuz! X3.3