2013-03-02 4 views
10

मान लीजिए मैं दो फ़ाइलें, en.csv और sp.csv, प्रत्येक युक्त ठीक दो अल्पविराम से अलग रिकॉर्ड है:यूनिक्स के साथ बाहरी जुड़ने के लिए सभी क्षेत्रों को कैसे प्राप्त करें?

en.csv:

1,dog,red,car 
3,cat,white,boat 

sp.csv:

2,conejo,gris,tren 
3,gato,blanco,bote 

अगर मैं निष्पादित

join -t, -a 1 -a 2 -e MISSING en.csv sp.csv 

उत्पादन मैं मिलता है:

1,dog,red,car 
2,conejo,gris,tren 
3,cat,white,boat,gato,blanco,bote 

सूचना है कि सभी लापता क्षेत्रों नष्ट किया गया। "उचित" पूर्ण बाहरी जुड़ने के लिए, मुझे एक प्रारूप निर्दिष्ट करने की आवश्यकता है; इस प्रकार

join -t, -a 1 -a 2 -e MISSING -o 0,1.2,1.3,1.4,2.2,2.3,2.4 en.csv sp.csv 

पैदावार इस तरह से एक पूर्ण बाहरी निर्माण करने के लिए शामिल होने के

1,dog,red,car,MISSING,MISSING,MISSING 
2,MISSING,MISSING,MISSING,conejo,gris,tren 
3,cat,white,boat,gato,blanco,bote 

एक दोष यह एक स्पष्ट रूप से अंतिम तालिका के प्रारूप है, जो कार्यक्रम संबंधी में क्या करने के लिए आसान नहीं हो सकता है निर्दिष्ट करने के लिए की जरूरत है कि है अनुप्रयोग (जहां शामिल टेबल की पहचान केवल रनटाइम पर जानी जाती है)।

जीएनयू join के हाल के संस्करण विशेष प्रारूप auto का समर्थन करके इस कमी को खत्म करते हैं। इसलिए, join के इस तरह के एक संस्करण के साथ पिछले आदेश ऊपर कहीं अधिक सामान्य

join -t, -a 1 -a 2 -e MISSING -o auto en.csv sp.csv 

द्वारा प्रतिस्थापित किया जा सकता है मैं join के संस्करणों कि -o auto विकल्प का समर्थन नहीं करते के साथ इस एक ही प्रभाव कैसे प्राप्त कर सकते हैं?


पृष्ठभूमि और विवरण

मैं एक यूनिक्स शेल (zsh) स्क्रिप्ट है कि प्रक्रियाओं के लिए डिज़ाइन किया गया है कई सीएसवी flatfiles, और GNU join 'एस' के व्यापक उपयोग करके ऐसा नहीं करता है है - ओ ऑटो 'विकल्प। मुझे इस स्क्रिप्ट को संशोधित करने की आवश्यकता है ताकि यह उन वातावरणों में काम कर सके जहां उपलब्ध join कमांड -o auto विकल्प का समर्थन नहीं करता है (जैसा बीएसडी join के साथ-साथ जीएनयू join के पुराने संस्करणों के लिए भी है)।

लिपि में इस विकल्प का एक विशिष्ट इस्तेमाल होता है कुछ की तरह:

_reccut() { 
    cols="1,$1" 
    shift 
    in=$1 
    shift 
    if (($# > 0)); then 
     join -t, -a 1 -a 2 -e 'MISSING' -o auto \ 
      <(cut -d, -f $cols $in | sort -t, -k1) \ 
      <(_reccut "[email protected]") 
    else 
     cut -d, -f $cols $in | sort -t, -k1 
    fi 
} 

मैं वर्णन करने के लिए है कि यह एक स्पष्ट प्रारूप के साथ -o auto को बदलने के लिए है, क्योंकि खेतों इस में शामिल करने के लिए मुश्किल होगा इस उदाहरण को दिखाने प्रारूप रनटाइम तक ज्ञात नहीं हैं।

फ़ंक्शन _reccut मूल रूप से फ़ाइलों से कॉलम निकालता है, और परिणामी तालिकाओं को उनके पहले कॉलम में जोड़ता है।देखने के लिए कैसे _reccut कार्रवाई में, कल्पना, जैसा कि ऊपर उल्लेख फ़ाइलों के अलावा, हम भी

2,Kaninchen,Grau,Zug 
1,Hund,Rot,Auto 

फिर फ़ाइल

de.csv था, उदाहरण के लिए, साथ-साइड कॉलम 3 में से प्रदर्शित करने के लिए en.csv, कॉलम 2 और sp.csv के 4, और de.csv एक के कॉलम 3 चलाने होगा:

% _reccut 3 en.csv 2,4 sp.csv 3 de.csv | cut -d, 2- 
red,MISSING,MISSING,Rot 
MISSING,conejo,tren,Grau 
white,gato,bote,MISSING 
+1

वास्तव में क्या आप Sun4 के साथ एक 1 बंद परियोजना के लिए के बारे में बात कर रहे हैं करना था, मैं आपको लगता है अपने आप को कोडिंग के साथ फंस गया है, या अपने इंस्टॉलेशन के हिस्से के रूप में नए जीएनयू में शामिल हो रहा है। क्षमा करें, लेकिन शुभकामनाएँ। – shellter

+1

मुझे लगता है कि मुझे जोड़ना चाहिए, बहुत गड़बड़ी के बाद, मैं बहुत कम परेशानी के साथ, अजीब assays करने में घायल हो गया। सौभाग्य। – shellter

उत्तर

1

यहाँ एक समाधान है कि या अपने डेटा के लिए काम नहीं कर सकते हो सकता है। यह लाइन संख्या द्वारा सीएसवी फ़ाइल के भीतर रिकॉर्ड्स को संरेखित करके समस्या का सामना करता है, यानी 2 लाइन 2 पर समाप्त होता है, लाइन 3123 पर 3123 रिकॉर्ड करें और इसी तरह। रिकॉर्ड गुम/लाइनों MISSING क्षेत्रों के साथ गद्देदार रहे हैं, ताकि इनपुट फ़ाइलें इस तरह देखने के लिए घायल किया जाएगा:

en.csv:

1,dog,red,car 
2,MISSING,MISSING,MISSING 
3,cat,white,boat 

de.csv:

1,Hund,Rot,Auto 
2,Kaninchen,Grau,Zug 
3,MISSING,MISSING,MISSING 

sp.csv:

1,MISSING,MISSING,MISSING 
2,conejo,gris,tren 
3,gato,blanco,bote 

एफ रोम वहां ब्याज के कॉलम को काटना आसान है और paste का उपयोग करके उन्हें साइड-बाय-साइड प्रिंट करना आसान है।

इस लक्ष्य को हासिल करने के लिए, हम इनपुट फ़ाइलों पहले सॉर्ट और फिर कुछ बेवकूफ awk जादू लागू होते हैं: एक रिकार्ड उनके अपेक्षित लाइन नंबर पर दिखाई देता है

  • है, यह
  • अन्यथा, प्रिंट के रूप में कई प्रिंट अपेक्षित संख्या वाली रेखाएं (यह फ़ाइल में पहली पंक्ति के फ़ील्ड की संख्या पर आधारित है, जैसा कि join -o auto करता है) MISSING फ़ील्ड जब तक संरेखण सही नहीं होता है
  • सभी इनपुट फ़ाइलें नहीं जा रही हैं रिकॉर्ड्स की एक ही संख्या, इसलिए अधिकतम से पहले इसकी खोज की जाती है। फिर, MISSING फ़ील्ड के साथ अधिक लाइनें अधिकतम हिट होने तक मुद्रित की जाती हैं।

कोड

reccut.sh:

#!/bin/bash 

get_max_recnum() 
{ 
    awk -F, '{ if ($1 > max) { max = $1 } } END { print max }' "[email protected]" 
} 

align_by_recnum() 
{ 
    sort -t, -k1 "$1" \ 
     | awk -F, -v MAXREC="$2" ' 
      NR==1 { for(x = 1; x < NF; x++) missing = missing ",MISSING" } 
      { 
       i = NR 
       if (NR < $1) 
       { 
        while (i < $1) 
        { 
         print i++ missing 
        } 
        NR+=i 
       } 
      }1 
      END { for(i++; i <= MAXREC; i++) { print i missing } } 
      ' 
} 

_reccut() 
{ 
    local infiles=() 
    local args=([email protected]) 
    for arg; do 
     infiles+=("$2") 
     shift 2 
    done 
    MAXREC="$(get_max_recnum "${infiles[@]}")" __reccut "${args[@]}" 
} 

__reccut() 
{ 
    local cols="$1" 
    local infile="$2" 
    shift 2 

    if (($# > 0)); then 
     paste -d, \ 
      <(align_by_recnum "${infile}" "${MAXREC}" | cut -d, -f ${cols}) \ 
      <(__reccut "[email protected]") 
    else 
     align_by_recnum "${infile}" "${MAXREC}" | cut -d, -f ${cols} 
    fi 
} 

_reccut "[email protected]" 

भागो

$ ./reccut.sh 3 en.csv 2,4 sp.csv 3 de.csv 
red,MISSING,MISSING,Rot 
MISSING,conejo,tren,Grau 
white,gato,bote,MISSING 
+0

इस पर कुछ प्रतिक्रिया पाने के लिए अच्छा होगा, क्या यह आपके लिए काम करता है? –

संबंधित मुद्दे

 संबंधित मुद्दे