سؤال

ما هي أفضل طريقة لقراءة سجل طول ثابت في بيرل. أنا أعرف قراءة ملف مثل:

ABCDE 302
DEFGC 876

ويمكنني القيام به

while (<FILE>) {
   $key = substr($_, 0, 5);
   $value = substr($_, 7, 3);
}

ولكن ليس هناك طريقة للقيام بذلك مع قراءة / فك؟

هل كانت مفيدة؟

المحلول

تحديث: لإجابة شافية، انظر الجواب جوناثان ليفلر أدناه

وأنا لن تستخدم هذه لحقول اثنين فقط (فما استقاموا لكم فاستقيموا استخدام حزمة / فك مباشرة)، ولكن لمدة 20 أو 50 أو حتى حقول أود أن استخدام <ل أ href = "http://search.cpan.org/dist/Parse-FixedLength/FixedLength.pm" يختلط = "noreferrer"> تحليل :: FixedLength (ولكن أنا منحاز). مثلا (على سبيل المثال الخاص بك) (تحديث: أيضا، يمكنك استخدام $ / و <> كبديل للقراءة ($ FH، $ BUF، $ buf_length) ... انظر أدناه):

use Parse::FixedLength;

my $pfl = Parse::FixedLength->new([qw(
  key:5
  blank:1
  value:3
)]);
# Assuming trailing newline
# (or add newline to format above and remove "+ 1" below)
my $data_length = $pfl->length() + 1;

{
  local $/ = \$data_length;
  while(<FILE>) {
    my $data = $pfl->parse($_);
    print "$data->{key}:$data->{value}\n";
    # or
    print $data->key(), ":", $data->value(), "\n";
  }
}

وهناك بعض وحدات مماثلة التي تجعل حزمة / فك أكثر "ودية" (انظر "انظر أيضا" من تحليل :: FixedLength).

تحديث: نجاح باهر، وهذا كان من المفترض أن يكون الجواب بديلة، وليس رد رسمي ... حسنا، لأنه هو ما هو عليه، يجب أن تشمل بعض من التعليمات البرمجية جوناثان لفلر أكثر مباشرة إلى الأمام، والتي من المرجح كيف ينبغي عادة ما تفعل ذلك (انظر حزمة / <لأ href = "HTTP: //perldoc.perl كافيه / وظائف / unpack.html "يختلط =" noreferrer "> مستندات فك العقدة وجوناثان لفلر أدناه):

$_ = "ABCDE 302";
my($key, $blank, $value) = unpack "A5A1A3";

نصائح أخرى

my($key, $value) = unpack "A5 A3";    # Original, but slightly dubious

ونحن على حد سواء بحاجة للتحقق من الخيارات في فك الصفحات اليدوية (و، على وجه الخصوص، و حزمة الصفحات اليدوية).

ومنذ المشغل حزمة يزيل فراغات زائدة، المثال الخاص بك يمكن المشفرة على النحو التالي:

my($key, $value) = unpack "A6A3";

وبدلا من ذلك (وهذا هو بيرل، لذلك TMTOWTDI):

my($key, $blank, $value) = unpack "A5A1A3";

1 هو اختياري ولكن منهجي ومتماثل. ميزة واحدة من هذا هو أنه يمكنك التحقق من أن $blank eq " ".

وافترض 10 سجلات شخصية اثنين من خمسة حقول شخصية لكل سجل:

open(my $fh, "<", $filename) or die $!;
while(read($fh, $buf, 10)) {
  ($field1, $field2) = unpack("A5 A5", $buf);
  # ... do something with data ...
}

وإليك طريقة أخرى للقيام بذلك:

while (<FILE>)
{
    chomp;
    if (/^([A-Z]{5}) ([0-9]{3})$/)
    {
        $key = $1;
        $value = $2;
    }
}

وبغض النظر عما إذا السجلات والحقول هي ذات طول ثابت، إذا يتم فصل الحقول المحددات موحدة (مثل مسافة أو فاصلة)، يمكنك استخدام وظيفة انقسام بسهولة أكثر من فك.

my ($field1, $field2) = split / /;

وابحث عن وثائق الانقسام. هناك اختلافات مفيدة على قائمة وسيطة وعلى شكل نمط محدد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top