Linux 标识单个unix目录中文本文件中的模式

Linux 标识单个unix目录中文本文件中的模式,linux,shell,unix,awk,sed,Linux,Shell,Unix,Awk,Sed,如果我想在一个目录中识别Unix中的模式,我可以知道哪个Unix实用程序会有帮助吗(比如awk) 输入: $ls a_20171007_001.txt a_20171007_002.txt b_20171007_001.txt c_20180101_001.txt 预期输出: a_20171007_002.txt b_20171007_001.txt 无论文件创建时间如何,输出都应基于文件名返回文件的最新版本 输出文件不应具有未来日期的文件(例如,当前日期:20171008,因此20180101

如果我想在一个目录中识别Unix中的模式,我可以知道哪个Unix实用程序会有帮助吗(比如awk)

输入:

$ls

a_20171007_001.txt
a_20171007_002.txt
b_20171007_001.txt
c_20180101_001.txt

预期输出:

a_20171007_002.txt
b_20171007_001.txt

  • 无论文件创建时间如何,输出都应基于文件名返回文件的最新版本
  • 输出文件不应具有未来日期的文件(例如,当前日期:20171008,因此20180101不应出现在输出中)
  • 关于如何在unix(awk或sed)中轻松实现这一点的任何建议


    非常感谢您的所有解决方案。但不幸的是,如果文件名不遵循任何模式,则没有帮助

    例如,输入:

    ab_bc_全部\u 20171008\u 001.txt

    bc_cd_ad_全部\u 20171008\u 001.txt

    ab_bc_全部\u 20171008\u 002.txt

    ad_dc_cd_ed_全部\u 20180101\u 001.txt

    ae_bc_zx_ed_ac_全部\u 20170918_001.txt

    输出:

    bc_cd_ad_all_20171008_001.txt

    ab_bc_all_20171008_002.txt

    ae_bc_zx_ed_ac_all_20170918_001.txt

    在上述情况下,仅在'all'之后显示日期字段。 在上述情况下,你能提出建议吗


    提前谢谢。

    请尝试以下内容,并让我知道这是否对您有帮助

    ls -ltr *.txt | awk -v date=$(date +%Y) -F"_" 'prev != $1 && val && date_val<=date{print val} {prev=$1;val=$0;date_val=substr($2,1,4)} END{if(date_val<=date){print val}}'
    

    ls-ltr*.txt | awk-v date=$(date+%Y)-F“|”prev!=$1&&val&&date\u val类似于Perl中的内容:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use feature qw{ say };
    
    use Time::Piece;
    
    my $today = localtime->ymd("");
    my %latest;
    for my $file (glob '*.txt') {
        my ($id, $date, $num) = split /[_.]/, $file;
        $latest{$id}{$date} = $num
            if $date <= $today
            && (! exists $latest{$id}
                || ! exists $latest{$id}{$date}
                || $num > $latest{$id}{$date});
    }
    for my $id (keys %latest) {
        for my $date (keys %{ $latest{$id} }) {
            say "$id\_$date\_$latest{$id}{$date}.txt";
        }
    }
    
    #/usr/bin/perl
    使用警告;
    严格使用;
    使用特征qw{say};
    使用时间::件;
    my$today=localtime->ymd(“”);
    我的最新百分比;
    对于我的$file(glob'*.txt'){
    我的($id,$date,$num)=拆分/[\.]/,$file;
    $latest{$id}{$date}=$num
    如果$date$latest{$id}{$date});
    }
    对于我的$id(密钥%latest){
    对于我的$date(键%{$latest{$id}}){
    说“$id\\$date\\$latest{$id}{$date}.txt”;
    }
    }
    
    GNUAwk静态文件名格式的解决方案
    \uuuuuu.txt

    示例性
    ls-1
    输出(扩展):



    一个简单的awk解决方案

    $ awk -F_ -vdate=`date +%Y%m%d` ' !($1 in file) && $2<=date {file[$1]=$0} ($1 in file){if($0>=file[$1]){file[$1]=$0}} END{ for(i in file)print file[i] }' f1
    a_20171007_002.txt
    b_20171007_001.txt
    
    $awk-F_-vdate=`date+%Y%m%d`!($1在文件中)和&$2=文件[$1]){文件[$1]=$0}}END{for(i在文件中)打印文件[i]}'f1
    a_20171007_002.txt
    b_20171007_001.txt
    
    说明:

    yyyymmdd

    在迭代记录/文件名时,如果文件名中的日期,即
    $2
    小于或等于
    当前日期
    ,并且前缀(例如a、b等)在数组
    文件中不存在,则将其存储在
    文件
    数组中,例如
    文件['a']=a_20171007_001.txt
    否则它不会被存储,在本例中,
    c_20180101_001.txt
    将被直接拒绝


    对于下一条记录,如果数组
    文件
    中存在
    前缀
    ,即
    $1
    ,则检查整个记录是否大于现有记录(按字典顺序)。如果是,覆盖
    文件
    数组中的记录。

    $ls-1r|awk-v today=“$(日期+%Y%m%d)”-F''.'($2此记录仅在shell(破折号)中可用

    $ ls -1r | awk -v today="$(date +%Y%m%d)" -F'_' '($2 <= today) && !seen[$1,$2]++'
    b_20171007_001.txt
    a_20171007_002.txt
    
    规格变更??? 试试这个

    d=$(date +%Y%m%d)
    ls -1r *_*_*.txt|while read l
    do
     b="${l%_*_*}"
     a="${l#$b*_}"
     c="${a%_*}"
     [ "$c" -le "$d" ] && [ "$v" != "$b$c" ] && { echo "$l";v="$b$c";}
    done
    

    您的版本号中可以有4位数字吗?如果是,它们是否只在999之后开始?例如
    a_20171007_999.txt
    a_20171007_1000.txt
    ?您能解释一下为什么这可以解决问题,而不是仅仅发布一些代码吗?这将更有帮助,特别是对初学者,谢谢。不,它是完全清晰、明显和简短的因此,任何不了解它的人都会从浏览手册页中受益匪浅。我想你要求对这个简短、琐碎的答案进行解释,但不是对这个页面上更长、更复杂的答案进行解释,因为有一个工具将它标记为可能的低质量,因为它非常简短。如果你不了解这个领域,那么就不要评论,只要move on.Compact代码很好而且很有帮助。但是解释是必要的,您也可以链接或引用一些手册页。或者对命令的作用进行非常简短的解释。这是您的决定,但这将提高答案的质量,当然也可以防止低质量的标志。
    b_20171007_004.txt
    a_20171007_0010.txt
    
    $ awk -F_ -vdate=`date +%Y%m%d` ' !($1 in file) && $2<=date {file[$1]=$0} ($1 in file){if($0>=file[$1]){file[$1]=$0}} END{ for(i in file)print file[i] }' f1
    a_20171007_002.txt
    b_20171007_001.txt
    
    $ ls -1r | awk -v today="$(date +%Y%m%d)" -F'_' '($2 <= today) && !seen[$1,$2]++'
    b_20171007_001.txt
    a_20171007_002.txt
    
    d=$(date +%Y%m%d)
    ls -1r *_*_*.txt|while IFS='_' read w x y
    do
     [ "$x" -le "$d" ] && [ "$v" != "$w$x" ] && { echo "$w"_"$x"_"$y";v="$w$x";}
    done
    
    d=$(date +%Y%m%d)
    ls -1r *_*_*.txt|while read l
    do
     b="${l%_*_*}"
     a="${l#$b*_}"
     c="${a%_*}"
     [ "$c" -le "$d" ] && [ "$v" != "$b$c" ] && { echo "$l";v="$b$c";}
    done