Как улучшить скрипт для поиска из нескольких файлов CSV - PullRequest
0 голосов
/ 01 февраля 2019

Мне нужно улучшить мой скрипт ниже, который принимает входной файл, содержащий почти миллион уникальных строк.В каждой строке у нее разные значения в 3 файлах поиска, которые я намерен добавить в свой вывод в виде значений, разделенных запятыми.

Приведенный ниже скрипт работает нормально, но для завершения работы требуются часы.Я ищу действительно быстрое решение, которое также было бы менее тяжелым для системы.

#!/bin/bash
while read -r ONT
do
{

ONSTATUS=$(grep "$ONT," lookupfile1.csv | cut -d" " -f2)
CID=$(grep "$ONT." lookupfile3.csv | head -1 | cut -d, -f2)
line1=$(grep "$ONT.C2.P1," lookupfile2.csv | head -1 | cut -d"," -f2,7 | sed 's/ //')
line2=$(grep "$ONT.C2.P2," lookupfile2.csv | head -1 | cut -d"," -f2,7 | sed 's/ //')
echo "$ONT,$ONSTATUS,$CID,$line1,$line2" >> BUwithPO.csv
} & 
done < inputfile.csv

inputfile.csv содержит строки, показанные ниже:

343OL5:LT1.PN1.ONT1
343OL5:LT1.PN1.ONT10
225OL0:LT1.PN1.ONT34
225OL0:LT1.PN1.ONT39
343OL5:LT1.PN1.ONT100
225OL0:LT1.PN1.ONT57

lookupfile1.csv содержит:

343OL5:LT1.PN1.ONT100, Down,Locked,No
225OL0:LT1.PN1.ONT57, Up,Unlocked,Yes
343OL5:LT1.PN1.ONT1, Down,Unlocked,No
225OL0:LT1.PN1.ONT34, Up,Unlocked,Yes
225OL0:LT1.PN1.ONT39, Up,Unlocked,Yes

lookupfile2.csv содержит:

225OL0:LT1.PN1.ONT34.C2.P1, +123125302766,REG,DigitMap,Unlocked,_media_BNT,FD_BSFU.xml,
225OL0:LT1.PN1.ONT57.C2.P1, +123125334019,REG,DigitMap,Unlocked,_media_BNT,FD_BSFU.xml,
225OL0:LT1.PN1.ONT57.C2.P2, +123125334819,REG,DigitMap,Unlocked,_media_BNT,FD_BSFU.xml,
343OL5:LT1.PN1.ONT100.C2.P11, +123128994019,REG,DigitMap,Unlocked,_media_ANT,FD_BSFU.xml,

lookupfile3.csv содержит:

343OL5:LT1.PON1.ONT100.SERV1,12-654-0330
343OL5:LT1.PON1.ONT100.C1.P1,12-654-0330
343OL5:LT7.PON8.ONT75.SERV1,12-664-1186
225OL0:LT1.PN1.ONT34.C1.P1.FLOW1,12-530-2766
225OL0:LT1.PN1.ONT57.C1.P1.FLOW1,12-533-4019

вывод:

225OL0:LT1.PN1.ONT57, Up,Unlocked,Yes,12-533-4019,+123125334019,FD_BSFU.xml,+123125334819,FD_BSFU.xml
225OL0:LT1.PN1.ONT34, Up,Unlocked,Yes,12-530-2766,+123125302766,FD_BSFU.xml,
343OL5:LT1.PN1.ONT1, Down,Unlocked,No,,,
343OL5:LT1.PN1.ONT100, Down,Locked,No,,,
343OL5:LT1.PN1.ONT10,,,,
225OL0:LT1.PN1.ONT39, Up,Unlocked,Yes,,,

Ответы [ 3 ]

0 голосов
/ 02 февраля 2019

Если, как вы указали в комментариях, вы не можете использовать решение, предоставляемое @tshiono из-за отсутствия gensub, предоставляемого GNU awk, вы можете заменить gensub двумя вызовами на sub навременная переменная для выполнения усечения необходимого суффикса.

Пример:

awk '
FILENAME=="lookupfile1.csv" {
    sub(",$", "", $1);
    onstatus[$1] = $2
}
FILENAME=="lookupfile2.csv" {
    split($2, a, ",")
    if (sub("\\.C2\\.P1,$", "", $1)) line1[$1] = a[1]","a[6]
    else if (sub("\\.C2\\.P2,$", "", $1)) line2[$1] = a[1]","a[6]
}
FILENAME=="lookupfile3.csv" {
    split($0, a, ",")
#     ont = gensub("(\\.ONT[0-9]+).*", "\\1", 1, a[1])
    sfx = a[1]
    sub(/^.*[.]ONT[^.]*/, "", sfx)
    sub(sfx, "", a[1])
#     cid[ont] = a[2]
    cid[a[1]] = a[2]
}
FILENAME=="inputfile.csv" {
    print $0","onstatus[$0]","cid[$0]","line1[$0]","line2[$0]
}
' lookupfile1.csv lookupfile2.csv lookupfile3.csv inputfile.csv > BUwithPO.csv

Я прокомментировал использование gensub в части, связанной с FILENAME=="lookupfile3.csv" и заменил выражение gensub двумя вызовами sub, используя sfx (суффикс) в качестве временной переменной.

Попробуйте и дайте мне знать, если вы можете использовать это.

0 голосов
/ 02 февраля 2019

Решение Perl

Следующий скрипт аналогичен решению awk, но написан на Perl.Сохраните его как filter.pl и сделайте его исполняемым.

#!/usr/bin/env perl

use strict;
use warnings;

my %lookup1;
my %lookup2_1;
my %lookup2_2;
my %lookup3;

while( <> ) {
    if ( $ARGV eq 'lookupfile1.csv' ) {
        # 225OL0:LT1.PN1.ONT34, Up,Unlocked,Yes
        # ^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ 
        if (/^([^,]+),\s*(.*)$/) {
            $lookup1{$1} = $2;
        }
    } elsif ( $ARGV eq 'lookupfile2.csv' ) {
        # 225OL0:LT1.PN1.ONT34.C2.P1, +123125302766,REG,DigitMap,Unlocked,_media_BNT,FD_BSFU.xml,
        # ^^^^^^^^^^^^^^^^^^^^        ^^^^^^^^^^^^^                                  ^^^^^^^^^^^ 
        if (/^(.+ONT\d+)\.C2\.P1,\s*([^,]+),(?:[^,]+,){4}([^,]+)/) {
            $lookup2_1{$1} = "$2,$3";
        } elsif (/^(.+ONT\d+)\.C2\.P2,\s*([^,]+),(?:[^,]+,){4}([^,]+)/) {
            $lookup2_2{$1} = "$2,$3";
        }
    } elsif ( $ARGV eq 'lookupfile3.csv' ) {
        # 225OL0:LT1.PN1.ONT34.C1.P1.FLOW1,12-530-2766
        # ^^^^^^^^^^^^^^^^^^^^             ^^^^^^^^^^^
        if (/^(.+ONT\d+)[^,]+,\s*(.*)$/) {
            $lookup3{$1} = $2;
        }
    } else { # assume 'inputfile.csv'
        no warnings 'uninitialized'; # because not all keys ($_) have values in the lookup tables
        # 225OL0:LT1.PN1.ONT34
        chomp;
        print "$_,$lookup1{$_},$lookup3{$_},$lookup2_1{$_},$lookup2_2{$_}\n";        
    }
}

Выполните его так:

./filter.pl lookupfile{1,2,3}.csv inputfile.csv > BUwithPO.csv

Важно, чтобы файлы поиска были первыми (как в решениях awk), кстати.) потому что они строят четыре словаря ( хэши на языке Perl) %lookup1, %lookup2_1 и т. д., а затем значения из inputfile.csv сопоставляются с этими словарями.

0 голосов
/ 02 февраля 2019

Как вы увидите, узкое место будет выполнять grep в цикле несколько раз.Вы можете повысить эффективность, создав справочную таблицу с ассоциативными массивами.
Если доступно awk, попробуйте следующее:

[Обновить]

#!/bin/bash

awk '
FILENAME=="lookupfile1.csv" {
    sub(",$", "", $1);
    onstatus[$1] = $2
}
FILENAME=="lookupfile2.csv" {
    split($2, a, ",")
    if (sub("\\.C2\\.P1,$", "", $1)) line1[$1] = a[1]","a[6]
    else if (sub("\\.C2\\.P2,$", "", $1)) line2[$1] = a[1]","a[6]
}
FILENAME=="lookupfile3.csv" {
    split($0, a, ",")
    if (match(a[1], ".+\\.ONT[0-9]+")) {
        ont = substr(a[1], RSTART, RLENGTH)
        cid[ont] = a[2]
    }
}
FILENAME=="inputfile.csv" {
    print $0","onstatus[$0]","cid[$0]","line1[$0]","line2[$0]
}
' lookupfile1.csv lookupfile2.csv lookupfile3.csv inputfile.csv > BUwithPO.csv

{EDIT]

Если вам нужно указать абсолютные пути к файлам, попробуйте:

#!/bin/bash

awk '
FILENAME ~ /lookupfile1.csv$/ {
    sub(",$", "", $1);
    onstatus[$1] = $2
}
FILENAME ~ /lookupfile2.csv$/ {
    split($2, a, ",")
    if (sub("\\.C2\\.P1,$", "", $1)) line1[$1] = a[1]","a[6]
    else if (sub("\\.C2\\.P2,$", "", $1)) line2[$1] = a[1]","a[6]
}
FILENAME ~ /lookupfile3.csv$/ {
    split($0, a, ",")
    if (match(a[1], ".+\\.ONT[0-9]+")) {
        ont = substr(a[1], RSTART, RLENGTH)
        cid[ont] = a[2]
    }
}
FILENAME ~ /inputfile.csv$/ {
    print $0","onstatus[$0]","cid[$0]","line1[$0]","line2[$0]
}
' /path/to/lookupfile1.csv /path/to/lookupfile2.csv /path/to/lookupfile3.csv /path/to/inputfile.csv > /path/to/BUwithPO.csv

Надеюсь, это поможет.

...