2012-12-19 12 views
6

मेरे पास एकाधिक फ़ाइलों को एक साथ जोड़ने के लिए निम्न कोड है। यह ठीक काम करता है लेकिन मैं रिक्त मानों को 0 पर प्रतिस्थापित करना चाहता हूं, इसलिए मैंने "0" उपयोग किया। लेकिन यह काम नहीं करता है। कोई विचार?बैश खाली प्रतिस्थापन (-e विकल्प) के साथ कई फ़ाइलों में शामिल हो

for k in `ls file?` 
do 
    if [ -a final.results ] 
    then 
      join -a1 -a2 -e "0" final.results $k > tmp.res 
      mv tmp.res final.results 
    else 
      cp $k final.results 
    fi 

done 

उदाहरण:

file1: 
a 1 
b 2 
file2: 
a 1 
c 2 
file3: 
b 1 
d 2 

Results: 
a 1 0 1 0 
b 2 1 0 
c 2 
d 2 

expected: 
a 1 1 0 
b 2 0 1 
c 0 2 0 
d 0 0 2 
+0

'एलएस' के आउटपुट का विश्लेषण न करें; बस फाइल के लिए 'के लिए उपयोग करें ?; do'। साथ ही, फ़ाइल नाम में विशेष वर्णों के खिलाफ सुरक्षा के लिए '$ k' के विस्तार का उद्धरण दें। – chepner

उत्तर

4

यह खराब दस्तावेज़ीकरण किया गया है, लेकिन जब join-e विकल्प केवल -o विकल्प के साथ संयोजन के रूप में काम करता है का उपयोग कर। ऑर्डर स्ट्रिंग को लूप के चारों ओर हर बार संशोधित करने की आवश्यकता होती है। निम्नलिखित कोड आपके वांछित आउटपुट उत्पन्न करना चाहिए।

i=3 
orderl='0,1.2' 
orderr=',2.2' 
for k in $(ls file?) 
do 
    if [ -a final.results ] 
    then 
      join -a1 -a2 -e "0" -o "$orderl$orderr" final.results $k > tmp.res 
      orderl="$orderl,1.$i" 
      i=$((i+1)) 
      mv tmp.res final.results 
    else 
      cp $k final.results 
    fi 
done 

जैसा कि आप देख सकते हैं, यह गन्दा हो जाता है। यदि आपको इसे और अधिक विस्तारित करने की आवश्यकता है तो यह अजीब या पायथन जैसे बीफियर टूल को संदर्भित करने योग्य हो सकता है।

+1

यह अभी भी बहुत सही नहीं है ... यह आपके स्क्रिप्ट का आउटपुट है: एक 1 1 1 0 ख 2 2 0 1 सी 2 0 2 0 घ 2 0 0 2 – Amir

+1

है कि शायद इसलिए है क्योंकि आपके पास एक मौजूदा final.results फ़ाइल है। पहले इसे हटाने का प्रयास करें। मेरा आउटपुट उस व्यक्ति के समान है जिसे आप पूछते हैं। – cmh

+0

हां। आपके उदाहरण final.results के साथ, इस स्क्रिप्ट को चलाने से '1 1 1 0 बी 2 2 0 1 सी 2 0 2 0 डी 2 0 0 2' ऊपर दिया गया है।जाहिर है, आपको फिर से चलने से पहले उस फ़ाइल को हटाने की जरूरत है। – cmh

0

मैं में शामिल होने का उपयोग कर छोड़ दिया और दूसरी तरह के

keywords=`cat file? | awk '{print $1}' | sort | uniq | xargs` 
files=`ls file? | xargs` 
for p in $keywords 
do 
    x=`echo $p` 
    for k in $files 
    do 
    if grep -q ^$p $k 
    then 
     y=`cat $k | grep ^$p | awk '{print $2}'` 
     x=`echo $x $y` 
    else 
     echo $p $k 
     x=`echo $x 0`  
    fi 
    done 
    echo $x >> final.results 
done 
1

में मेरी पटकथा लिखी मान लिया जाये कि एक एकल फाइल में कोई डुप्लिकेट चाबी देखते हैं और चाबी, आप gawk इस्तेमाल कर सकते हैं खाली स्थान के शामिल नहीं है और का एक क्रमबद्ध ग्लोब फ़ाइलें। यह दृष्टिकोण बड़ी फ़ाइलों के लिए काफी तेज़ होगा और सभी डेटा के ग्लोब की तुलना में केवल अपेक्षाकृत कम मात्रा में स्मृति का उपयोग करेगा। भागो की तरह:

gawk -f script.awk $(ls -v file*) 

script.awk की सामग्री:

BEGINFILE { 
    c++ 
} 

z[$1] 

$1 in a { 

    a[$1]=a[$1] FS ($2 ? $2 : "0") 
    next 
} 

{ 
    for(i=1;i<=c;i++) { 
     r = (r ? r FS : "") \ 
     (i == c ? ($2 ? $2 : "0") : "0") 
    } 

    a[$1]=r; r="" 
    b[++n]=$1 
} 

ENDFILE { 

    for (j in a) { 
     if (!(j in z)) { 
      a[j]=a[j] FS "0" 
     } 
    } 

    delete z 
} 

END { 

    for (k=1;k<=n;k++) { 
     print b[k], a[b[k]] 
    } 
} 

टेस्ट इनपुट/grep . file* के परिणाम:

file1:a 1 
file1:x 
file1:b 2 
file2:a 1 
file2:c 2 
file2:g 
file3:b 1 
file3:d 2 
file5:m 6 
file5:a 4 
file6:x 
file6:m 7 
file7:x 9 
file7:c 8 

परिणाम:

a 1 1 0 4 0 0 
x 0 0 0 0 0 9 
b 2 0 1 0 0 0 
c 0 2 0 0 0 8 
g 0 0 0 0 0 0 
d 0 0 2 0 0 0 
m 0 0 0 6 7 0 
4

एक अलग रूप में, जीएनयू versio शामिल होने के n -o auto का समर्थन करता है। -e और -o लोगों को अजीब सीखने के लिए पर्याप्त निराशा का कारण बनता है। (How to get all fields in outer join with Unix join? भी देखें)। चूंकि सीएमएच ने कहा: यह दस्तावेज नहीं है, लेकिन -e विकल्प में शामिल होने का उपयोग करते समय केवल -o विकल्प के साथ मिलकर काम करता है।

जनरल समाधान:

cut -d ' ' -f1 file? | sort -u > tmp.index 
for k in file?; do join -a1 -e '0' -o '2.2' tmp.index $k > tmp.file.$k; done 
paste -d " " tmp.index tmp.file.* > final.results 
rm tmp* 

बोनस: मैं कैसे Git में कई शाखाओं की तुलना करते हैं?

for k in pmt atc rush; do git ls-tree -r $k | cut -c13- > ~/tmp-branch-$k; done 
cut -f2 ~/tmp-branch-* | sort -u > ~/tmp-allfiles 
for k in pmt atc rush; do join -a1 -e '0' -t$'\t' -11 -22 -o '2.2' ~/tmp-allfiles ~/tmp-branch-$k > ~/tmp-sha-$k; done 
paste -d " " ~/tmp-allfiles ~/tmp-sha-* > final.results 
egrep -v '(.{40}).\1.\1' final.results # these files are not the same everywhere 
+0

मुझे लगता है कि आपका पहला बिंदु एक तरफ से कम है और सही उत्तर _ का अधिक है। यह वांछित प्रभाव वाले 'जुड़ने' के विकल्प देता है। – WAF

+0

वापस देखकर, यह मेरे पहले गिट ऑक्टोपस विलय से ठीक पहले है। हमने तीन शाखाओं की तुलना की जब तक कि सभी अंतर शून्य न हों :-) –

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

  • कोई संबंधित समस्या नहीं^_^