gpt4 book ai didi

linux - perl while 循环

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:00:53 24 4
gpt4 key购买 nike

在这段代码中,我解析了一个文件(包含 ls -lrt 的输出)以获得日志文件的修改日期。然后我将所有日志文件移动到一个新文件夹中,并将它们的修改日期添加到文件名中,然后将所有这些文件打包成一个 tar。

我遇到的问题是在 while 循环中。因为它正在读取所有文件的数据,所以 while 循环持续运行 15 次。我知道代码中存在一些问题,但我无法弄清楚。

在 while 循环内,我拆分 ls -lrt 记录以查找日志文件的修改日期。 $file 是我存储在文本文件 /scripts/yagya.txt 中的 ls 命令的输出,以便进行修改日期。但是 while 循环执行了 15 次,因为文件夹中有 15 个日志文件与模式匹配。

#!/usr/bin/perl
use File::Find;
use strict;

my @field;
my $filenew;
my $date;
my $file = `ls -lrt /scripts/*log*`;
my $directory="/scripts/*.log";
my $current = localtime;
my $current_time = $current;
$current_time = s/\s+//g;
my $freetime = $current_time;
my $daytime = substr($current_time,0,8);
my $seconddir = "/$freetime/";

system ("mkdir $seconddir");

open (MYFILE,">/scripts/yagya.txt");
print MYFILE "$file";
close (MYFILE);

my $data = "/scripts/yagya.txt";
my $datas = "/scripts/";
my %options = (
wanted => \&wanted,
untaint => 1
);

find (\%options, $datas);
sub wanted {
if (/[._]log\d*$/){
my $files;
my @fields;
my $fields;
chomp;
$files=$_;

open (MYFILE,$data);
while(<MYFILE>){
chop;
s/#.*//;
next unless /\S/;
@fields = (split)[5,6,7];
$fields = join('',@fields), "\n";
}
close (MYFILE);

system ("mv $files $seconddir$fields$files");
}
}

system ("tar cvf /$daytime/$daytime.tar.gz /$daytime/*log*");
system ("rm $seconddir*log*");

system ("rm $data");

最佳答案

您的代码很难阅读。在开始测试之前,您似乎已经将程序编写为一个大块。这种工作方式很常见,但却是非常错误的。您应该首先实现程序的一小部分并对其进行测试,然后再添加更多功能、再次测试等等。这样一来,您就不会因为在未经测试的大型程序中同时解决许多问题而不知所措。

如果您在程序顶部的 use strict 中添加 use warnings 也会对您有很大帮助。它有助于捕获您可能忽略的简单错误。

此外,您是否知道 File::Find 每次遇到文件时都会调用您的 wanted 回调子例程?它不会一次传递所有文件。

问题似乎是您一直在阅读 yagya.txt 文件,而当您找到与 File::的当前文件匹配的记录时,您应该停止阅读: Find 找到了。您需要做的是检查 ls 输出中的当前记录是否以当前文件的名称结尾。如果你这样写循环

while (<MYFILE>) {
if (/\Q$files\E$/) {
my @fields = (split)[5,6,7];
$fields = join('',@fields);
last;
}
}

然后 $fields 将以当前文件的修改日期结束,这就是您想要的。

但是如果您使用 Perl 为您读取文件修改日期,这会容易一千倍。

与其将 ls 列表写入文件并读回,不如这样做

use File::stat;

my $mtime = localtime(stat($files)->mtime);

这将为您提供类似 Wed Jun 13 11:25:23 2012 的字符串。我的 ls 输出中的日期仅包括月份名称、日期和时间,例如 Jun 8 12:37。这不是很具体,您也许至少应该包括一年,但是要从此 $mtime 生成相同的字符串,您可以编写

my $fields = join '', (split ' ', $mtime)[1,2,3];

关于您的计划,我还有很多话要说,但我希望现在这对您有用。


我注意到的另外几件事:

  • $current_time = s/\s+//g 应该是 $current_time =~ s/\s+//g 以删除所有空格当前时间字符串

  • Sun Jun 3 11:50:54 2012 这样的值将被缩减为 SunJun311:53:552012$daytime 将采用不正确的值 SunJun31

关于linux - perl while 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11011940/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com