如果我想在一个目录中识别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
有关如何在unix(awk或sed)中轻松实现此目的的任何建议
非常感谢您的所有解决方案。但不幸的是,如果文件名不遵循任何模式,它就无济于事。
例如,输入:
ab_bc_ 所有 _20171008_001.txt
bc_cd_ad_ 所有 _20171008_001.txt
ab_bc_ 所有 _20171008_002.txt
ad_dc_cd_ed_ 所有 _20180101_001.txt
ae_bc_zx_ed_ac_ 所有 _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'之后的日期字段出现。 你可以在上面的案例中建议..
提前致谢。
答案 0 :(得分:1)
在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";
}
}
答案 1 :(得分: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
<强>解释强>
以date
yyyymmdd
变量中
在迭代记录/文件名时,如果文件名中的日期$2
小于或等于current date
且前缀(例如a,b等)不存在在数组file
中,然后将其存储在file
数组中,例如。 file['a']=a_20171007_001.txt
否则它将无法存储,在此示例中,c_20180101_001.txt
将被直接拒绝。
对于下一条记录,如果数组prefix
中存在$1
即file
,则检查整个记录是否大于现有记录(按字典顺序排列)。如果是,请覆盖file
数组中的记录。
答案 2 :(得分:0)
请您试着跟随并告诉我这是否对您有帮助。
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_val<=date{
print val
}
{
prev=$1;
val=$0
date_val=substr($2,1,4)
}
END{
if(date_val<=date){
print val
}
}'
答案 3 :(得分:0)
GNU Awk 静态文件名格式<prefix>_<date>_<version>.txt
的解决方案:
示例性ls -1
输出(扩展):
a_20171007_001.txt
a_20171007_002.txt
b_20171007_001.txt
c_20180101_001.txt
a_20171007_0010.txt
b_20171007_004.txt
ls -1 | awk -F'[_.]' '{ k=$1"_"$2 }{ if (a[k]<$3) a[k]=$3 }
END{
for (i in a) {
split(substr(i, index(i,"_")+1), b, "");
ts=mktime(sprintf("%d %d %d 00 00 00",b[1]b[2]b[3]b[4],b[5]b[6],b[7]b[8]));
if (systime() >= ts) print i"_"a[i]".txt"
}
}'
输出:
b_20171007_004.txt
a_20171007_0010.txt
答案 4 :(得分:0)
这个只在shell(破折号)
中没问题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
答案 5 :(得分:-1)
$ ls -1r | awk -v today="$(date +%Y%m%d)" -F'_' '($2 <= today) && !seen[$1,$2]++'
b_20171007_001.txt
a_20171007_002.txt