引用符内の区切り記号を無視

引用符内の区切り記号を無視

次の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であることはわかりますが、このように1行で書く方が簡単です。

おすすめ記事