여러 데이터 열 정렬

여러 데이터 열 정렬

입력(정렬되지 않음, 불량)

"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-44432"
,"XYZ-ZTE-43255"
"XYZ-ZTE-52775 serverB110 agreed",
"XYZ-ZTE-79213 - serverB688 agreed",
"XYZ-ZTE-77323 serverB617 agreed",
"XYZ-ZTE-81422 - serverB609 agreed","XYZ-ZTE-77323"
"XYZ-ZTE-32785 - serverA626 agreed","XYZ-ZTE-52775"
"XYZ-ZTE-43235 - serverA605 disagreed (asdfjlasdj yxvv il lkyeas sadfa)","XYZ-ZTE-43235"
"XYZ-ZTE-11591 serverB144 agreed",
,"XYZ-ZTE-11591"

출력(정렬됨, 필요한 항목, 좋은 항목!)

"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-43255"
,"XYZ-ZTE-44432"
"XYZ-ZTE-52775 serverB110 agreed","XYZ-ZTE-52775"
"XYZ-ZTE-79213 - serverB688 agreed",
"XYZ-ZTE-77323 serverB617 agreed","XYZ-ZTE-77323"
"XYZ-ZTE-81422 - serverB609 agreed",
"XYZ-ZTE-32785 - serverA626 agreed",
"XYZ-ZTE-43235 - serverA605 disagreed (asdfjlasdj yxvv il lkyeas sadfa)","XYZ-ZTE-43235"
"XYZ-ZTE-11591 serverB144 agreed","XYZ-ZTE-11591"

간단히 말해서 이것은 두 개의 열을 포함하는 XLS의 일부입니다. 두 열은 다음과 같은 방식으로 함께 정렬되어야 합니다.

왼쪽 열의 XYZ-ZTE-77323은 오른쪽 열의 XYZ-ZTE-77323과 일치합니다.

그러나 다음과 같은 것도 있습니다.

,"XYZ-ZTE-43255"

이는 다음 줄과 일치해야 합니다.

"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-43255"

그러나 (입력의) 행에는 이미 올바른 열이 포함되어 있습니다.

"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-44432"

예를 들어, 다음과 같은 경우:

"XYZ-ZTE-44432"

왼쪽 열에 존재하지 않습니다. OUTPUT의 새 행에 있어야 합니다.

이 작업을 수행하는 방법을 아는 사람이 있나요?

답변1

나는 이 프로그램을 사용해 보았지만 최고의 프로그램은 아니지만(파일을 두 번 구문 분석하고 일부 중복된 코드가 있음) 필요에 맞게 자유롭게 적용할 수 있습니다. 나는 그것이 효과가 있다고 생각합니다.

$ cat script.pl
use warnings;
use strict;
use Text::CSV_XS;

my (%col1, %col2);

my $csv = Text::CSV_XS->new(
        { empty_is_undef => 1 }
) or die "Error: " . Text::CSV_XS->error_diag();

chomp( my @data = <STDIN> );

## Read file and save first column in %col1 hash and second
## column in %col2 hash.
foreach my $line ( @data ) {
    die "Error in parse of CSV file\n" unless $csv->parse( $line );
    my @columns = $csv->fields();
    $col1{ $columns[0] }++ if defined $columns[0];
    $col2{ $columns[1] }++ if defined $columns[1];
}

LINE:
foreach my $line ( @data ) {
        die "Error in parse of CSV file\n" unless $csv->parse( $line );
        my @columns = $csv->fields();

        ## Discard line if both columns are undefined.
        next if !defined $columns[0] && !defined $columns[1];

        ## 1.- Undefined first column: Save second column in hash.
        do { $col2{ $columns[1] } = 1; next } unless defined $columns[0];

        ## 2.- Both columns are defined: Sort them.
        if ( defined $columns[0] && defined $columns[1] ) {
                if ( index( $columns[0], $columns[1] ) > -1 ) {
                        # Line is sorted, print it.
                        print quote($columns[0]), ",", quote($columns[1]), "\n";
                        delete $col2{ $columns[1] };
                } else {
                        # Line unsorted, search its equivalent in hash of second column
                        # and print.
                        my $key = $1 if $columns[0] =~ /^(\S*)/;
                        print quote($columns[0]), ",", ( exists $col2{ $key } ? quote($key) : "" ), "\n";
                        delete $col2{ $key } if exists $col2{ $key };
                        # Here, the second unsorted column, search its equivalent in first
                        # column. If not found print it now, else it will be printed later.
                        for my $str ( keys %col1 ) {
                                next LINE if index( $str, $columns[1] ) > -1;
                        }
                        print ",", quote($columns[1]), "\n";
                }
                next;
        }

        ## 3.- Undefined second column: Check if second column is saved in
        ## hash and join it with first column.
        unless ( defined $columns[1] ) {
                my $key = $1 if $columns[0] =~ /^(\S*)/;
                print quote($columns[0]), ",", ( exists $col2{ $key } ? quote($key) : "" ), "\n";
                delete $col2{ $key } if exists $col2{ $key };
        }
}

sub quote {
        my ($str) = $_[0];
        $str =~ s/^(.*)$/"$1"/;
        return $str;
}

귀하의 데이터 파일:

"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-44432"
,"XYZ-ZTE-43255"
"XYZ-ZTE-52775 serverB110 agreed",
"XYZ-ZTE-79213 - serverB688 agreed",
"XYZ-ZTE-77323 serverB617 agreed",
"XYZ-ZTE-81422 - serverB609 agreed","XYZ-ZTE-77323"
"XYZ-ZTE-32785 - serverA626 agreed","XYZ-ZTE-52775"
"XYZ-ZTE-43235 - serverA605 disagreed (asdfjlasdj yxvv il lkyeas sadfa)","XYZ-ZTE-43235"
"XYZ-ZTE-11591 serverB144 agreed",
,"XYZ-ZTE-11591"

결과:

$ perl script.pl <yourdatafile
"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-43255"
,"XYZ-ZTE-44432"
"XYZ-ZTE-52775 serverB110 agreed","XYZ-ZTE-52775"
"XYZ-ZTE-79213 - serverB688 agreed",
"XYZ-ZTE-77323 serverB617 agreed","XYZ-ZTE-77323"
"XYZ-ZTE-81422 - serverB609 agreed",
"XYZ-ZTE-32785 - serverA626 agreed",
"XYZ-ZTE-43235 - serverA605 disagreed (asdfjlasdj yxvv il lkyeas sadfa)","XYZ-ZTE-43235"
"XYZ-ZTE-11591 serverB144 agreed","XYZ-ZTE-11591"

답변2

데이터베이스에 데이터를 채운 다음 조인을 사용하여 원하는 기준에 따라 데이터를 검색합니다. SQLite는 서버 구성 요소가 없는 멋진 경량 시스템으로, 이러한 방식으로 작은 데이터 세트를 조작하는 데 적합합니다.

답변3

그러면 Python을 사용하여 예상한 출력이 생성됩니다. 나는 Pyton을 잘 모르기 때문에 약간 해킹적이지만 작동합니다 :)

#!/bin/bash

python -c '
import sys, csv;
reader = csv.reader(sys.stdin)
nbli=0 # line number (to maintin input order)
nbwi=6 # width of line number.. (zero padded) 
left=[] 
rght=[] 
for row in reader:
    nbli+=1
    fnum=format(nbli, "0"+str(nbwi)+"d")
    if row[0] != "": left.append(row[0]+fnum) 
    if row[1] != "": rght.append(row[1]+fnum)
left.sort()
rght.sort()
coll = []
l ,r = 0, 0
while l < len(left) or r < len(rght):
    #
    if l >= len(left):
        numr = rght[r][-nbwi:]
        datr = rght[r][:len(rght[r])-nbwi]
        coll.append(numr + " " + ",\"" + datr + "\"")
        r+=1
    elif r >= len(rght):
        numl = left[l][-nbwi:]
        datl = left[l][:len(left[l])-nbwi]
        coll.append(numl + " " + "\"" + datl + "\",")
        l+=1
    else:
        numl = left[l][-nbwi:]
        numr = rght[r][-nbwi:]
        datl = left[l][:len(left[l])-nbwi]
        datr = rght[r][:len(rght[r])-nbwi]
        #
        if datl.startswith(datr+" "):
            coll.append(numl + " " + "\"" + datl + "\",\"" + datr + "\"")
            l+=1
            r+=1
        elif datl < datr + " ":
            coll.append(numl + " " + "\"" + datl + "\",")
            l+=1
        else:
            coll.append(numr + " " + ",\"" + datr + "\"")
            r+=1

coll.sort()
c = 0
while c < len(coll):
    print coll[c][nbwi+1:]
    c+=1
' \
<<-'STDIN'
"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-44432"
,"XYZ-ZTE-43255"
"XYZ-ZTE-52775 serverB110 agreed",
"XYZ-ZTE-79213 - serverB688 agreed",
"XYZ-ZTE-77323 serverB617 agreed",
"XYZ-ZTE-81422 - serverB609 agreed","XYZ-ZTE-77323"
"XYZ-ZTE-32785 - serverA626 agreed","XYZ-ZTE-52775"
"XYZ-ZTE-43235 - serverA605 disagreed (asdfjlasdj yxvv il lkyeas sadfa)","XYZ-ZTE-43235"
"XYZ-ZTE-11591 serverB144 agreed",
,"XYZ-ZTE-11591"
STDIN

산출:

"XYZ-ZTE-43255 serverB618 agreed","XYZ-ZTE-43255"
,"XYZ-ZTE-44432"
"XYZ-ZTE-52775 serverB110 agreed","XYZ-ZTE-52775"
"XYZ-ZTE-79213 - serverB688 agreed",
"XYZ-ZTE-77323 serverB617 agreed","XYZ-ZTE-77323"
"XYZ-ZTE-81422 - serverB609 agreed",
"XYZ-ZTE-32785 - serverA626 agreed",
"XYZ-ZTE-43235 - serverA605 disagreed (asdfjlasdj yxvv il lkyeas sadfa)","XYZ-ZTE-43235"
"XYZ-ZTE-11591 serverB144 agreed","XYZ-ZTE-11591"

관련 정보