【问题标题】:Perl substr to create fixed length filename from time and PIDPerl substr 根据时间和 PID 创建固定长度的文件名
【发布时间】:2017-01-31 10:51:18
【问题描述】:

我希望在这个小型代码项目上获得一些帮助或“第二双眼睛”。 我负责修复一些旧的 Perl 代码,这些代码将在新的 Web 服务器上运行。 该代码以秒为单位(自 1970 年以来)花费时间,连接破折号,连接服务器进程 ID 号以创建可变长度文件名。然后在许多下游流程中使用该文件和名称。

文件名创建代码为:$output_file = "$time-$$";

我遇到的问题是,在新服务器上,PID 最多可以是 6(或 7?)位,而旧服务器从未见过超过 5 位的 PID。其余的下游 perl 脚本都希望该 PID 文件名部分最多包含 5 位数字(当文件名的 PID 部分遇到 6 位数字时,程序会不正常地退出)。

所以我想要完成的是最终得到一个文件名,它始终是 16 个字符的固定长度。由 10 位时间码、一个破折号和一个 5 位 PID 号(如果 PID 大于 5 个字符,则为最右边的 5 位)组成。

我尝试创建一个 Perl 测试脚本来查看是否可以处理 PID 数据值。 (a) 如果是 6 位或 7 位字符,则使用 substr 命令将 PID 数据修剪为 5, (b) 或者如果小于 5,则增加到 5 个带前导零的字符,再次使用 substr 命令。 (a) 缩短它的情况似乎可以正常工作, 但是 (b) 试图使其更大的情况在服务器上的行为不一致。

如果可能的话,我想避免使用 grep 和正则表达式。 任何对我或其他支持人员以后难以破译的东西都没有用。

我的测试脚本的结构允许我确保我的所有测试用例都会产生正确的预期结果。 (而且我可能正在做一些完全错误/愚蠢的事情......)

我正在粘贴: (a) 我的测试脚本,(b) 服务器结果的屏幕快照。 服务器 PERL 版本:5.10.1

#!/usr/bin/perl -w
use strict;
use warnings;
# 
# Name: testsubstr2.pl
# 
my $pidnum7 = "1234567";
my $pidnum6 = "123456";
my $pidnum5 = "12345";
my $pidnum4 = "1234";
my $pidnum3 = "123";
my $pidnum2 = "12";
my $pidnum1 = "1";

if ( length( $pidnum7 ) == 7 )
{ print "This is 7 char PIDnum7. Length = ", length( $pidnum7 ), ", Content: ", $pidnum7, "\n";
 my $subst7  = substr ($pidnum7, -5, 5);
 print "  Now shortened as SUBst7 to: ", length($subst7), ", Content: ", $subst7, "\n";
 print "  Orig PIDnum7 is length: ", length($pidnum7), ", Content: ", $pidnum7, "\n";
}
else { } # do nothing
# this 7 down to 5 seems to work ok.

#elsif ( length( $pidnum6 ) == 6 )
if ( length( $pidnum6 ) == 6 )
# else the string is 6 (or less)
{ print "This is 6 char PIDnum6. Length = ", length( $pidnum6 ), ", Content: ", $pidnum6, "\n";
 my $subst6  = substr ($pidnum6, -5, 5);
 print "  Now  shortened as SUBst6 to: ", length($subst6), ", Content: ", $subst6, "\n";
 print "  Orig PIDnum6 is length: ", length($pidnum6), ", Content: ", $pidnum6, "\n";
}
else { } # do nothing
# this 6 down to 5 seems to work ok.

#elsif ( length( $pidnum5 ) == 5 )
if ( length( $pidnum5 ) == 5 )
# else the string is exactly 5, do nothing
{ print "This PIDnum5 is exactly 5 char PIDnum, Length = ", length( $pidnum5 ), ", Content: ", $pidnum5, "\n";
}
else { } # do nothing. Fine as is.

#elsif ( length( $pidnum4 ) == 4 )
if ( length( $pidnum4 ) == 4 )
# else the string is 4, too short
{ print "This is 4 char PIDnum4. Length = ", length( $pidnum4 ), ", Content: ", $pidnum4, "\n";
 my $subst4  = substr ($pidnum4, 0, 0, "0");   #insert character '0' in front
 print "  After substr command, PIDnum4 = ", length($pidnum4), ", Content: ", $pidnum4, "\n";
 print "  Now PID4 in variable SUBst4 is length: ", length($subst4), ", Content: ", $subst4, "\n";
# Weird Result in this code block, the var $pidnum4 becomes 5 chars, 01234, though it should not have changed
# but the temp var $subst4 becomes 0 charcters with Blank (no) content. It should I thought become the 5 character receiver.
# something wrong with this block of code.
}
else { } # do nothing

这是我的测试脚本运行的 Snaggy 链接server test results

(结果屏幕底部的 7 行来自我在测试脚本中包含的一些通用 substr 命令示例,可能不需要,因此我将它们排除在上面的代码示例之外。)

谢谢。

【问题讨论】:

  • 这闻起来像XY problem - 你想完成什么? Timestamp 是文件元数据,因此您不需要将其包含在文件名中。 pid通常是独一无二的东西。那么……为什么不改用Data::UUIDFile::Temp 呢?
  • 我的限制是这个网站和 Perl 脚本系统是在 90 年代后期开发的,以创建一个有保证的唯一文件名。因此,以秒为单位的时间加上一个 PID 号。这个名字本身没有特别的意义。由于有许多脚本函数和 HTML 编码页面需要这种文件名形式,并且如果 PID 部分长于 5 位,则无法处理文件名,所以我坚持让它工作。我没有获得(母公司非营利组织的)mgnt 团队的授权来重新编码整个网站。所以——必须尽我所能。
  • 加上当前生产网站上已经存在的数千个使用这种名称形式的数据文件。不过,这是一个值得提出的有效问题,希望原始编码人员对此的思考能够更加广泛。

标签: perl substr


【解决方案1】:

我会使用sprintf 和模,像这样:

#!/usr/bin/perl

while (<DATA>) {
        chomp;
        my $pid = $_;
        my $time = time;
        my $fn = sprintf("%s-%05d", $time, $pid % 100000);
        print "$fn\n";
}
__DATA__
1
12
123
12345
123456
7654321

输出:

1485862025-00001
1485862025-00012
1485862025-00123
1485862025-12345
1485862025-23456
1485862025-54321

这是否满足您的需求?

【讨论】:

  • 考虑到限制,这可能是我处理它的方式。虽然,我想我可能会考虑 not 使用“time-pid”文件名,而是使用 Data::UUIDFile::Temp,具体取决于具体用例。
  • 这看起来很有趣,我来看看。不过,我的测试脚本可能误导了大家,因为我已经尝试了 7 次,因为我想确保 substr(或任何命令)适用于遇到的所有不同 PID 长度的情况。在现实生活中,实时完整脚本一次只会创建一个文件名。因此,每个文件名数据创建只会运行一次。所以我会从这个角度来检查它。谢谢。
  • 我想我终于明白了模运算(花了一点时间)。因此,通过从 PID 值中减去(可以这么说)尽可能多的 100,000 个块,我们将得到始终小于 100,000 的余数。也就是说,它将是 99,999 的最大值,即 5 位数字。从而为我们提供了任意长度 PID 的最右边 5 位数字。哇有趣。我从来没有想过要那样做。我正在尝试字符串字符位置操作。我将创建一些测试脚本并在我的并行开发系统上检查它们。稍后再联系您。谢谢。 :)
猜你喜欢
  • 2011-01-25
  • 2021-10-15
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多