美文网首页
Perl中的文件名通配符和文件查找

Perl中的文件名通配符和文件查找

作者: dulunar | 来源:发表于2021-01-03 14:51 被阅读0次

    在Unix下进行文件夹的内容展示或者文件查找的时候,会大量的使用*来对文件名进行通配扩展,那么在使用Perl进行搭建流程的时候同样支持文件名通配。在Shell下,通配使用的是glob,一种特殊的模式匹配,也是最常见的通配符扩展,可以理解成精简版的正则表达式;Perl中的glob通配方式和Shell的通配方式是完全一致,因为Perl的glob函数直接调用系统的$SHELL来进行通配的。

    glob通配函数

    此处要注明,通配符 / glob 模式通常用来匹配目录以及文件,而不是文本,其语法:

    元字符 解释
    [] 字符类,匹配中括号中的任一字符
    * 匹配任意个字符
    ? 匹配任意单个字符,不包含0个
    [list] 匹配指定范围(list)内任意单个字符,可以是单个字符组成的集合
    [^list] 匹配指定范围(list)外的任意单个字符或字符集合
    {!list} [^list] 一致
    [str1,str2...] 匹配 srt1 或者 srt2 或者更多字符串,也可以是集合
    ~ 匹配家目录(/home/name)

    注意:

    1. []]支持[0-9] [a-z] [A-Z] [A-z]类似的范围通配,其中[A-z]等价于[A-Za-z]
    2. 不支持[^]取反
    3. 特别需要注意的是[1-34]通配的是[1234],而不是1到34,因为中括号只能匹配单个字符

    例子:

    my @F = glob '*'; print join ("\n",@F); # 匹配当前目录下所有非"."开头的隐藏文件
    my @F = glob '.* *'; print join ("\n",@F);  # 匹配当前目录下所有文件,包括"."开头的隐藏文件
    my @F = glob 'test.p[ly]'; print join ("\n",@F);    # 匹配test.pl或test.py文件
    my @F = glob '[0-9][0-9]*.pl'; print join ("\n",@F);    # 匹配两个数值开头的pl文件
    my @F = glob '~/test.p?'; print join ("\n",@F); # 匹配家目录下后缀以p开头,后面还有一个字符的文件
    my @F = glob '~/*.sh'; print join ("\n",@F);    # 匹配家目录下的所有sh文件
    

    在glob函数中,如果想要匹配包含空格的文件名,必须将其使用引号(单/双引号皆可)包围,如:匹配"123 test.txt"文件:

    glob '"123 t*.txt"';
    glob "'123 t*.txt'";
    

    尖括号<>通配写法

    尖括号表达式用于通配和glob的实现是一致的,仅仅尖括号改成了glob函数。例如匹配根目录下的".sh"文件:

    my @F = glob '~/*.sh';
    my @F = <~/*.sh>;
    
    my $dir = "/home/luna";
    my @F = glob '$dir/*.sh';
    my @F = <$dir/*.sh>;
    

    在这里一定要写正确通配符的格式,因为在perl中尖括号有时候是文件句柄,此处的解析规则是:假如尖括号内的内容满足标识符规则(文件句柄的名称要满足此规则),则会解析为文件句柄,否则解析成通配符。

    # 文件名通配符
    my @F = <path/*>;
    my @F = <$dir/*>;
    
    # 读取文件句柄
    my @li = <path>;
    my @li = <$line>;
    

    文件查找:find2perl脚本

    在Unix下有一个方便查找文件的工具——find。Perl提供了一个find2perl的工具(安装perl时会自带安装),它可以将find查找文件时的表达式转换成Perl对应的查找语句。

    find2perl的选项和用法和find的用法99%都一样,只有几项额外的是find2perl自身提供的,但这样的选项非常少。

    但是请注意,find2perl不是文件查找工具,只是将我们写的find命令表达式转换为等价的Perl文件查找语句。

    例如,搜索/etc目录下所有".conf"结尾的文件,find命令的表达式如下:

    find /etc -type f -name "*.conf"
    

    执行find2perl:

    find2perl /etc -type f -name "*.conf"
    

    屏幕会出现一堆代码:

    #! /usr/bin/perl -w
        eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
            if 0; #$running_under_some_shell
    
    use strict;
    use File::Find ();
    
    # Set the variable $File::Find::dont_use_nlink if you're using AFS,
    # since AFS cheats.
    
    # for the convenience of &wanted calls, including -eval statements:
    use vars qw/*name *dir *prune/;
    *name   = *File::Find::name;
    *dir    = *File::Find::dir;
    *prune  = *File::Find::prune;
    
    sub wanted;
    
    
    
    # Traverse desired filesystems
    File::Find::find({wanted => \&wanted}, '/etc');
    exit;
    
    
    sub wanted {
        my ($dev,$ino,$mode,$nlink,$uid,$gid);
    
        (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
        -f _ &&
        /^.*\.conf\z/s
        && print("$name\n");
    }
    
    
    

    可以看出,上面生成了一个wanted子程序,可以保存起来,以后需要在/etc下查找"*.conf"文件时,只需调用wanted子程序即可:

    find2perl /etc -type f -name "*.conf" > FindConfInEtc.pl
    chmod +x FindConfInEtc.pl
    ./FindConfInEtc.pl
    /etc/ltrace.conf
    /etc/pnm2ppa.conf
    /etc/brltty.conf
    /etc/signond.conf
    /etc/sysctl.conf
    /etc/gai.conf
    /etc/apg.conf
    ......
    

    References

    Linux shell 通配符 / glob 模式

    骏马金龙

                            —— dulunar 后记于 2020.12

    相关文章

      网友评论

          本文标题:Perl中的文件名通配符和文件查找

          本文链接:https://www.haomeiwen.com/subject/jqwuoktx.html