따옴표 안의 구분 기호 무시

따옴표 안의 구분 기호 무시

다음과 같은 aa 파일이 있습니다 .csv.

"ID0054XX","PT. SUMUT","18 JL.BONJOL","SUMATERA UTARA, NORTH","MEDAN","","ID9856","PDSUIDSAXXX","","","","Y"
"ID00037687","PAN INDONESIA, PT.","JALAN JENDERAL, SUDIRMAN, SENAYAN","","INDIA","","ID566543","PINBIDJAXXX","","0601","","Y"

,구분 기호로 사용되는 고유 변수 에 각 쉼표로 구분된 값을 할당하는 스크립트가 있습니다 .

스크립트 부분은 다음과 같습니다.

IFS=,

[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }

while read Key  Name    Address1        Address2        City    State   Country SwiftCode       Nid     Chips   Aba     IsSwitching
do
          echo "-------------------------------------------------------------------"

     echo "From Key : $Key"

    echo "-------------------------------------------------------------------"
          echo "-------------------------------------------------------------------"

     echo "From Name : $Name"

그것이 하는 일은 따옴표 안의 쉼표로 값을 분리하는 것이며, 내가 원하는 출력은 각 값을 해당 변수에서 고유하게 분리하는 것입니다.

나는 쉼표를 바꾸려고 시도했지만 IFS=[","]성공하지 못했습니다. 어떤 조언이나 도움이라도 대단히 감사하겠습니다.

답변1

여기서 몇 가지 잘못을 저지르고 있습니다.

  1. 쉘을 사용하여 텍스트를 구문 분석하고 있습니다.

    이것이 가능하긴 하지만 매우 비효율적입니다. 느리고, 쓰기 어렵고, 읽기 어렵고, 올바르게 실행하기 어렵습니다. 쉘은 이런 종류의 작업을 위해 설계되지 않았습니다.

  2. csv 파서 없이 csv 파일을 파싱하려고 합니다.

    CSV는 단순한 형식이 아닙니다. 여기와 같이 구분 기호가 있는 필드를 가질 수 있습니다. 여러 행에 걸쳐 있는 필드를 가질 수도 있습니다. 간단한 패턴 일치를 사용하여 임의의 CSV 데이터를 구문 분석하는 것은 매우 복잡하고 정확하게 수행하기가 매우 어렵습니다.

나쁘고 해키적인 해결책은 다음과 같습니다.

$ sed 's/","/"|"/g' file.csv | 
    while IFS='|' read -r Key Name Address1 Address2 City \
     State Country SwiftCode Nid Chips Aba IsSwitching; do 
        echo "From Key : $Key"; echo "From Name : $Name"; 
    done
From Key : "ID0054XX"
From Name : "PT. SUMUT"
From Key : "ID00037687"
From Name : "PAN INDONESIA, PT."

","이는 구분 기호 로 "|"사용된 모든 것을 대체합니다 |. 물론, 필드에 |.

좋고 깔끔한 방법은 적절한 스크립트 언어(셸이 아님)와 csv 파서를 사용하는 것입니다. 예를 들어 Perl 1 에서는 다음과 같습니다 .

$ cat file.csv | perl -MText::CSV -le '
    $csv = Text::CSV->new({binary=>1}); 
    while ($row = $csv->getline(STDIN)){ my ($Key, $Name, $Address1, $Address2, $City, $State, $Country, $SwiftCode, $Nid, $Chips, $Aba, $IsSwitching) = @$row;
print "From Key: $Key\nFrom Name: $Name";}' 
From Key: ID0054XX
From Name: PT. SUMUT
From Key: ID00037687
From Name: PAN INDONESIA, PT.
    

또는 스크립트로:

#!/usr/bin/perl -l
use strict;
use warnings;
use Text::CSV;

open(my $fh, "file.csv");
my $csv = Text::CSV->new({binary=>1}); 
while (my $row = $csv->getline($fh)){
    my (
            $Key, $Name, $Address1, $Address2, $City,
            $State, $Country, $SwiftCode, $Nid, $Chips,
            $Aba, $IsSwitching
         ) = @$row;
    print "From Key: $Key\nFrom Name: $Name";
}

Text::CSV모듈을 먼저 설치 해야 하며 ( ), ( 대부분의 배포판에서는 패키지) 을 cpanm Text::CSV설치해야 할 수도 있습니다 .cpanmcpanminus

또는 Python 3에서는 다음과 같습니다.

#!/usr/bin/env python3

import csv
with open('file.csv', newline='') as csvfile:
    linereader = csv.reader(csvfile, delimiter=',', quotechar='"')
    for row in linereader:
        print("From Key: %s\nFrom Name: %s" % (row[0], row[1]))
    

위의 Python 코드를 스크립트로 저장하고 파일에서 실행하면 다음이 인쇄됩니다.

$ foo.py
From Key: ID0054XX
From Name: PT. SUMUT
From Key: ID00037687
From Name: PAN INDONESIA, PT.
    

1 예, 이것이 UUoC인 것은 알지만 이렇게 한 줄로 작성하는 것이 더 간단합니다.

관련 정보