按文件名中的非常规日期对文件进行排序 (PHP)

发布于 2024-11-02 12:19:57 字数 1202 浏览 0 评论 0原文

我正在使用一个 PHP 脚本,该脚本允许按时间顺序浏览 Eggdrop 生成的 IRC 日志。最初,我读取目录内容并根据文件修改日期将日志名称插入到数组中。然而,在最近的服务器移动之后,文件的修改日期已更新,导航现在变得混乱!

日志文件名结构如下所示:

channel.log.dayMONTHyear.txt

例如:

shrawberry.log.08Apr2011.txt

由于非常易于人类阅读,因此很难正确排序。

由于月份代码始终是三个字符长并且位于序列中的可预测位置,因此我可以手动将非标准日期代码解析为 Unix 时间戳,迭代列表并将每个项目添加到具有该时间戳的数组中,然后排序按该数字排列的数组。

但这听起来有些过分了。

我是否有钱,或者我提出的解决方案是否理想?


在 Marc B. 的帮助下,我实现了以下内容:

function dateFromEggLog($string){
    $month = substr($string,-11,-8);
    $day = substr($string,-13,-11);
    $year = substr($string,-8,-4);

    for($i=1;$i<=12;$i++){
        if(strtolower(date("M", mktime(0, 0, 0, $i, 1, 0))) == strtolower($month)){
            $month = $i;
            break;
        }
    }

    return "$year-$month-$day";
}

function my_compare($a, $b) {
    $a_date = dateFromEggLog($a);
    $b_date = dateFromEggLog($b);
    if ($a_date == $b_date) {
        return 0;
    }
    $a = strtotime($a_date); // convert to PHP timestamp
    $b = strtotime($b_date); // convert to PHP timestamp

    return (($a < $b) ? -1 : 1);
}

这成功地对我的日志进行了排序,而无需修改我的数组。

I'm working with a PHP script that allows the chronological browsing of Eggdrop-generated IRC logs. Initially, I was reading the directory contents and inserting the log names into an array based on file modification date. After a recent server move, however, the files have had their modification dates updated and the navigation is now disorderly!

The log filename structure looks like:

channel.log.dayMONTHyear.txt

for example:

shrawberry.log.08Apr2011.txt

which, for being quite human-readable, is difficult to order properly.

Since the month code is always three characters long and comes in a predictable position in the sequence, I could manually parse the nonstandard date code into a Unix timestamp, iterate through the list and add each item to an array with that timestamp, and then sort the array by that number.

But that sounds excessive.

Am I on the money, or is the solution I proposed ideal?


With Marc B.'s help, I've implemented the following:

function dateFromEggLog($string){
    $month = substr($string,-11,-8);
    $day = substr($string,-13,-11);
    $year = substr($string,-8,-4);

    for($i=1;$i<=12;$i++){
        if(strtolower(date("M", mktime(0, 0, 0, $i, 1, 0))) == strtolower($month)){
            $month = $i;
            break;
        }
    }

    return "$year-$month-$day";
}

function my_compare($a, $b) {
    $a_date = dateFromEggLog($a);
    $b_date = dateFromEggLog($b);
    if ($a_date == $b_date) {
        return 0;
    }
    $a = strtotime($a_date); // convert to PHP timestamp
    $b = strtotime($b_date); // convert to PHP timestamp

    return (($a < $b) ? -1 : 1);
}

This successfully sorts my logs, without needing to muck around with my array.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

九厘米的零° 2024-11-09 12:19:57

您的示例文件名与“看起来像”示例不匹配 - “txt”和日期字符串颠倒了。但无论如何,您可以使用 PHP usort() 函数,它可以让用户定义的函数进行比较。

它可能不是特别有效,但你会这样做:

function my_compare($a, $b) {
    $a_date = ... extract date field from filename in $a
    $b_date = ... extract date field from filename in $b
    if ($a_date == $b_date) {
        return 0;
    }
    $a = strtotime($a_date); // convert to PHP timestamp
    $b = strtotime($b_date); // convert to PHP timestamp

    return (($a < $b) ? -1 : 1);
}

usort($array_of_filenames, 'my_compare');

Your example filename doesn't match the "looks like" sample - the 'txt' and date string are reversed. but in any case, you can use the PHP usort() function, which lets a user-defined function do the comparisons.

It may not be particularly efficient, but you'd do something like this:

function my_compare($a, $b) {
    $a_date = ... extract date field from filename in $a
    $b_date = ... extract date field from filename in $b
    if ($a_date == $b_date) {
        return 0;
    }
    $a = strtotime($a_date); // convert to PHP timestamp
    $b = strtotime($b_date); // convert to PHP timestamp

    return (($a < $b) ? -1 : 1);
}

usort($array_of_filenames, 'my_compare');
不醒的梦 2024-11-09 12:19:57

你以前用过filemtime吗?为什么现在不使用 filectime 呢?

You used filemtime before? Why not use filectime now?

拿命拼未来 2024-11-09 12:19:57

为什么不在排序函数中使用字符串操作将 channel.log.dayMONTHyear.txt 重新排序为 channel.log.yyyymmdd.txt,然后使用基本字符串比较?

<?php

/* Helper stuff */

$months = Array(
  "Jan" => "01", "Feb" => "02", "Mar" => "03",
  "Apr" => "04", "May" => "05", "Jun" => "06",
  "Jul" => "07", "Aug" => "08", "Sep" => "09",
  "Oct" => "10", "Nov" => "11", "Dec" => "12"
);

/* The hard work */

function convertLogFilename($file) {

   $pos = strpos($file, ".log.");
   if ($pos === FALSE)
      throw new Exception("Invalid log file format");

   $pos += strlen(".log.");

   $dd   = substr($file, $pos, 2);
   $mm   = substr($file, $pos + 2, 3);
   $yyyy = substr($file, $pos + 5, 4);

   return substr($file, 0, $pos) . "$yyyy${months[$mm]}$dd.txt";
}

function sort_func($a, $b) {
   return convertLogFilename($a) < convertLogFilename($b);
}


/* Your program */

$files = Array(
   "channel.log.18Apr2011.txt",
   "channel2.log.21Jan2002.txt"
);

usort($files, 'sort_func');
print_r($files);
?>

输出:

Array
(
    [0] => channel2.log.21Jan2002.txt
    [1] => channel.log.18Apr2011.txt
)

这应该比为每个文件名创建完整日期表示要快得多。

Why not, in your sort function, re-order channel.log.dayMONTHyear.txt to channel.log.yyyymmdd.txt using string manipulation, then use basic string comparison?

<?php

/* Helper stuff */

$months = Array(
  "Jan" => "01", "Feb" => "02", "Mar" => "03",
  "Apr" => "04", "May" => "05", "Jun" => "06",
  "Jul" => "07", "Aug" => "08", "Sep" => "09",
  "Oct" => "10", "Nov" => "11", "Dec" => "12"
);

/* The hard work */

function convertLogFilename($file) {

   $pos = strpos($file, ".log.");
   if ($pos === FALSE)
      throw new Exception("Invalid log file format");

   $pos += strlen(".log.");

   $dd   = substr($file, $pos, 2);
   $mm   = substr($file, $pos + 2, 3);
   $yyyy = substr($file, $pos + 5, 4);

   return substr($file, 0, $pos) . "$yyyy${months[$mm]}$dd.txt";
}

function sort_func($a, $b) {
   return convertLogFilename($a) < convertLogFilename($b);
}


/* Your program */

$files = Array(
   "channel.log.18Apr2011.txt",
   "channel2.log.21Jan2002.txt"
);

usort($files, 'sort_func');
print_r($files);
?>

Output:

Array
(
    [0] => channel2.log.21Jan2002.txt
    [1] => channel.log.18Apr2011.txt
)

This ought to be significantly quicker than creating full date representations for each filename.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文