ประมวลผลข้อมูลข้อความล้วน


0

ฉันเป็นไฟล์ข้อความธรรมดาที่ฉันต้องตรวจสอบโดยอัตโนมัติและเขียนผลลัพธ์ในไฟล์ข้อความธรรมดาอีกไฟล์ โปรดทราบว่าฉันจะใช้ข้อความธรรมดาและ CSV แทนกันเนื่องจาก CSV เป็นข้อความธรรมดาที่มีตัวคั่นทั่วไประหว่างข้อมูล (จุลภาคแท็บ ฯลฯ )

ตัวอย่างข้อมูล

ABD-01A
ABD-01B
ABD-01C
AL-25A
AL-25B

ดำเนินการหนึ่ง - จดจำสองส่วนแรกของข้อมูล ( text- number) เพื่อทำซ้ำและนับใน CSV ที่ส่งออก:

ABD-01,1
ABD-01,2
ABD-01,3
AL-25,1
AL-25,2

กระบวนการที่สอง - ส่วนแรกของข้อมูลที่รวบรวมไว้ด้านบนมีประเภทของคีย์หลักที่กำหนดให้กับไฟล์อื่น ฉันต้องการรับคีย์หลักที่กล่าวถึงในไฟล์ที่สร้างขึ้นใหม่เช่นกัน:

#primary key file
1,ABD-01
2,ABD-02
3,AL-02
20,AL-25

#newly generated file
1,ABD-01,1
1,ABD-01,2
1,ABD-01,3
20,AL-25,1
20,AL-25,2

โดยพื้นฐานแล้วสิ่งที่ฉันถามเธอคือหากมีซอฟต์แวร์ใดที่สามารถช่วยฉันได้ทั้งในระบบปฏิบัติการ Windows หรือ Linux Bash สามารถช่วยฉันในการประมวลผลที่ง่ายขึ้น แต่ฉันไม่คิดว่ามันจะสามารถจัดการกับสิ่งนี้ได้มากนัก กรุณาแนะนำ


ข้อมูลเดียวกันสามารถเกิดขึ้นได้หลายครั้งในไฟล์เดียวกันได้หรือไม่? (ตัวอย่างเช่น " , , " ... )ABD-01AABD-01BAL-25AABD-01A
grawity

@grawity ไม่ข้อมูลทั้งหมดไม่ซ้ำใคร
Oxwivi

ในกรณีนี้คุณสามารถใช้สคริปต์ตัวอย่างที่ฉันให้ไว้ในความคิดเห็นอื่นของฉัน (ทั้งสองทำสิ่งเดียวกัน แต่เขียนในภาษาต่าง ๆ เพื่อให้คุณสามารถเปรียบเทียบได้)
grawity

คำตอบ:


1
  1. เลือกภาษาที่คุณต้องการ - Perl ทำงานได้ดีกับข้อความ Python, PHP และ Ruby นั้นโอเคถ้าช้ากว่านิดหน่อย
  2. อ่านไฟล์คีย์ก่อน:
    • แยกแต่ละkey,dataสายเข้าkeyและdata,
    • จากนั้นเก็บทั้งสองใน dict / hash / array: keys[data] = key
    • ยังcounts[data] = 0ถ้าเริ่มต้นความต้องการภาษา
  3. อ่านไฟล์ข้อมูลทั้งหมด:
    1. ใช้ regexp เพื่อค้นหาข้อมูล "TEXT-NUMBER" ที่จุดเริ่มต้นของทุกบรรทัด
    2. เพิ่มขึ้นทีละcounts[data]หนึ่ง
    3. และทันทีที่การส่งออกkeys[data], counts[data]เส้นและ

ฉันเขียนตัวอย่างสคริปต์ทั้งใน Perl และ Python ดังนั้นทางเลือกของคุณ:

process.pl

#!/usr/bin/env perl
use strict;

sub usage {
    print "Usage: $0 <key_file> <data_file...>\n";
    return 2;
}

my $keys_file = shift(@ARGV) // exit(usage);
my @data_files = @ARGV;

my %keys;   # $data => $primarykey
my %counts; # $data => $count

# Read keys

open(my $fh, "<", $keys_file) or die "$!";
while (my $line = <$fh>) {
    chomp($line);
    my ($key, $datum) = split(/,/, $line, 2);
    if (!defined $datum) {
        warn "$keys_file: line $. not in KEY,DATA format: '$line'\n";
        next;
    }

    $keys{$datum} = $key;
    $counts{$datum} = 0;
}
close($fh);

# Read and output data

my $ex = qr/^(\w+-\d+)\w*/;
for my $data_file (@data_files) {
    open(my $fh, "<", $data_file) or die "$!";
    while (my $line = <$fh>) {
        chomp($line);
        if ($line =~ /$ex/) {
            my $datum = $1;
            if (!defined $keys{$datum}) {
                warn "no primary key found for data '$datum'\n";
                next;
            }

            # Increment count, then print processed line immediately
            $counts{$datum}++;
            print "$keys{$datum},$&,$counts{$datum}\n";
        }
        else {
            warn "$data_file: line $. does not begin with TEXT-NUMBER: '$_'\n";
        }
    }
    close($fh);
}

process.py

#!/usr/bin/env python
from __future__ import print_function
import sys
import re

def usage():
    print("Usage: %s <key_file> <data_file...>" % sys.argv[0])
    return 2

try:
    keys_file = sys.argv[1]
    data_files = sys.argv[2:]
except IndexError:
    sys.exit(usage())
except ValueError:
    sys.exit(usage())

keys = {}
counts = {}

# Read keys

for line in open(keys_file, "r"):
    try:
        key, datum = line.strip().split(",", 1)
    except ValueError:
        print("%s: line not in KEY,DATA format: %r" \
            % (keys_file, line.strip()), file=sys.stderr)
        continue

    keys[datum] = key
    counts[datum] = 0

# Read and output data

ex = re.compile(r'^(\w+-\d+)\w*')
for data_file in data_files:
    for line in open(data_file, "r"):
        line = line.strip()
        m = re.match(ex, line)
        if m:
            datum = m.group(1)
            if datum not in keys:
                print("no primary key found for data %r" % datum,
                    file=sys.stderr)
                continue

            # Increment count, then print processed line immediately
            counts[datum] += 1
            print("%s,%s,%d" % (keys[datum], m.group(0), counts[datum]))
        else:
            print("%s: line does not begin with TEXT-NUMBER: %r" \
                % (data_file, line.strip()), file=sys.stderr)

2

ฉันจะทำมันในหลามใช้การแสดงออกปกติ เพียงพิมพ์pythonเชลล์ของคุณเพื่อดูว่ามีการติดตั้งหรือไม่

มิฉะนั้นคุณสามารถใช้Perl เพียงพิมพ์perlเชลล์ของคุณเพื่อดูว่ามีการติดตั้งหรือไม่ คือได้ตัวในการสนับสนุนการแสดงผลปกติ


คุณสามารถให้ตัวอย่างเกี่ยวกับวิธีการใช้งานได้ไหม
Oxwivi

@Oxwivi: นี่คือบางส่วน แต่ไม่สามารถเรียนรู้ภาษาจาก "ตัวอย่างบางส่วน" ... "การเรียนรู้ Perl" และหนังสือที่คล้ายกันอาจเป็นการเริ่มต้นที่ดี
grawity

@grawity ขออภัยที่กลับมาช้ามากฉันประสบปัญหาที่ไม่คาดคิดในการสร้างข้อมูล ฉันทำสิ่งนี้: perl process.pl */images products.csv > images- ไฟล์ข้อมูลหลายไฟล์ แต่ไม่มีข้อขัดแย้ง อย่างไรก็ตามผลลัพธ์นั้นไม่มีกุญแจ - ตัวอย่างเช่น: ,ABD-47,2. พื้นที่ที่สงวนไว้สำหรับค่าคีย์ว่างเปล่า นอกจากนี้หากคุณต้องการโปรดเพิ่มคำตอบของคุณเองเนื่องจากเป็นไปได้ว่าฉันจะเลือกคุณ
Oxwivi

@grawity เฉพาะไฟล์ * / images แรกที่ถูกประมวลผล การอ้างอิงโดยตรงกับไฟล์นั้นทำงานตามที่คาดไว้
Oxwivi

@grawity สิ่งที่unmatched inputควรจะหมายถึงอะไร? ไม่พบไฟล์ที่ตรงกันในไฟล์คีย์?
Oxwivi

2

กระบวนการ 1

perl count.pl datafile 

โดยที่ count.pl เป็นสิ่งที่ต้องการ

#!perl
use strict;
use warnings;

my %headwordcount;

while (<>) {
  if (/^([A-Z]+-\d+)/) { $headwordcount{$1}++; }
  # else { warn "Bad data: $_"; } # uncomment line for data warnings
}

END {
  foreach (sort keys %headwordcount) {
     print "$_,$headwordcount{$_}\n";
  }
}

ยังไม่ได้ทดสอบ

กระบวนการ 2

เพิ่มสิ่งที่ชอบ

   my %key;

   BEGIN {
     my $keyfilename = 'primary.key';
     open my $fh, '<', $keyfilename or die "Can't read '$keyfilename' - $!\n";
     while (<$fh>) {
        chomp;
        my ($key,$headword) = split(/,/, $_, 2);
        $key{$headword} = $key;        
     }
     close $fh;
   }

และเปลี่ยนบรรทัดพิมพ์END {}เป็น

   print "$key{$_},$_,$headwordcount{$_}\n";

อีกครั้งยังไม่ทดลอง

คุณจะสร้างคำเตือนหากไฟล์ข้อมูลมีคำหลักที่ไม่ได้อยู่ในไฟล์คีย์ คุณสามารถตรวจสอบ$key{$_}ว่าไม่ได้กำหนดไว้และพิมพ์คีย์ถ้าไม่มี


สคริปต์นั้นควรทำอะไร กระบวนการแรกที่ฉันอธิบาย?
Oxwivi

@Oxwivi: ใช่ หากคุณไม่สามารถติดตามรหัสได้อย่างง่ายดาย มันอาจเป็นการดีที่สุดที่จะลองคำตอบอื่น หากคุณเข้าใจการเขียนสคริปต์ bash และ / หรือ awk Perl ไม่ควรยากเกินไป
RedGrittyBrick

ฉันใช้สคริปต์ทุบตีพื้นฐาน แต่ฉันไม่สามารถพูดได้ว่าฉันทำตามได้ดี (ส่วนใหญ่อินไลน์ไวยากรณ์) และฉันจะเพิ่มรหัสใหม่ที่คุณแก้ไขลงในคำตอบที่เยื้องหรือไม่
Oxwivi

@Oxwivi ใช่เพิ่มสิ่งใหม่ทันทีหลังจากmy %headwordcount;(นอกเหนือจากการเปลี่ยนprintสายแน่นอนซึ่งแทนที่หนึ่งในÈND … foreachวง)
RedGrittyBrick

โอเคขอบคุณมาก! สิ่งสุดท้ายสิ่งหนึ่ง - datafileจะถูกแทนที่ด้วยไฟล์อินพุตที่เห็นได้ชัด แต่...ต่อไปนี้เป็นบางสิ่ง Perl เฉพาะหรือไม่
Oxwivi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.