मेरे पास कुछ डेटा फ़ाइलें हैं जिनके लिए मैं एक "diff" कॉलम जेनरेट करना चाहता हूं, जिसका अर्थ है कि एक कॉलम जोड़ें जो इंगित करता है कि वर्तमान फ़ाइल से कोई विशेष लाइन जोड़ी/हटा दी गई है या नहीं। उदाहरण के लिए, मेरे पास निम्नलिखित दो फ़ाइलें हैं, a.csv:

id,data,data2
1,A,B
2,A,B
3,A,B
4,A,B

और b.csv:

id,data,data2
2,A,C
3,A,C
4,A,C
5,A,C

मैं केवल id के आधार पर तुलना करना चाहता हूं कि क्या कोई पंक्ति जोड़ी/निकाल दी गई है। डेटा कोई फर्क नहीं पड़ता। अब तक मैंने जो सबसे अच्छा तरीका निकाला है, वह है miller का निम्न तरीके से उपयोग करना:

#!/bin/bash

t1=$(mktemp)
t2=$(mktemp)
t3=$(mktemp)

mlr --icsv --ocsv put '$diff = "-"' then reorder -f diff a.csv > "$t1"
mlr --icsv --ocsv put '$diff = "+"' then reorder -f diff b.csv > "$t2"
mlr --icsv --ocsv join -f "$t1" -j id --ul --ur --np then unsparsify "$t2" > "$t3"
mlr --icsv --ocsv join -f "$t3" -j id --ul --ur      then unsparsify then reorder -f diff,id then sort -nf id b.csv

rm "$t1"
rm "$t2"
rm "$t3"

यह निम्नलिखित उत्पन्न करता है, जो मैं चाहता हूं:

diff,id,data,data2
-,1,A,B
,2,A,C
,3,A,C
,4,A,C
+,5,A,C

इस समाधान का दुर्भाग्यपूर्ण पहलू यह है कि इसे चार बार मिलर चलाने की जरूरत है और तीन अस्थायी फाइलों का उपयोग करता है। मिलर बैश प्रक्रिया प्रतिस्थापन (<() व्यवसाय) के साथ काम नहीं करता है।

क्या इस तरह के आउटपुट को उत्पन्न करने का कोई और सीधा तरीका है?

0
user8370684 18 जुलाई 2018, 19:41
आप प्रत्येक फ़ाइल पर cut -f1 -d',' कर सकते हैं और फिर diff पर पाइप कर सकते हैं?
 – 
jeremysprofile
18 जुलाई 2018, 19:43
धन्यवाद, लेकिन फिर मैं एक CSV आउटपुट फ़ाइल के साथ समाप्त नहीं होता जिसे मुझे आगे की प्रक्रिया करने की आवश्यकता है।
 – 
user8370684
18 जुलाई 2018, 19:45
एक एकल फ़ाइल में सभी डेटा प्राप्त करने के लिए एक join और तुलना करने और आवश्यक प्रारूप लिखने के लिए एक awk के बारे में क्या?
 – 
Poshi
18 जुलाई 2018, 22:16
इसके परिणामस्वरूप कम आमंत्रण होंगे लेकिन मूल रूप से इसका परिणाम मेरे लिखने के लिए एक कार्यक्रम होगा, जिसे मैं किसी भी भाषा में कर सकता था। मैं एक ऐसे टूल की तलाश में था जो इसे आसानी से कर सके।
 – 
user8370684
19 जुलाई 2018, 00:09
तुम सही हो। लेकिन जब कोड इतना आसान हो और उपकरण मौजूद न हो, तो जो उपलब्ध है उसका उपयोग करना अधिक हो सकता है, जैसा कि मामला है। वास्तव में, मिलर का उपयोग करके, आप स्वयं एक प्रोग्राम को कोडिंग भी कर रहे हैं: आप मिलर को बहुत सारे ऑर्डर किए गए ऑपरेशन करने के लिए कह रहे हैं।
 – 
Poshi
19 जुलाई 2018, 01:16

2 जवाब

एक विशेष टूल है: https://github.com/paulfitz/daff

यदि आप उदाहरण के लिए daff a.csv b.csv चलाते हैं तो आप प्राप्त करते हैं

---,1 ,A ,B → ,2 ,A ,B→C → ,3 ,A ,B→C → ,4 ,A ,B→C +++,5 ,A ,C

0
aborruso 10 पद 2018, 20:37

निम्नलिखित आउटपुट बिल्कुल वही है जो आपने पोस्ट किया था:

join -t, -11 -22 <(
        # the order of files here is important
        # filter out duplicates too
        sort -t, -u -k1,1 b.csv a.csv
    ) <(
        comm --output-delimiter=, <(
                <a.csv \
                cut -d, -f1 |
                sort
            ) <(
                <b.csv \
                cut -d, -f1 |
                sort
            ) | 
        # this is stupid, but needs to be done anyway
        sed '
            s/^,,/,/;t;
            s/^,/+,/;t;
            s/^/-,/
        '
    ) |
awk -vFS=, -vOFS=, '{print $4,$1,$2,$3}'

लेकिन हम join -o auto और सरल awk के साथ रास्ता छोटा कर सकते हैं:

join -t, -11 -21  -a1 -a2 -o auto a.csv b.csv | 
awk -vFS=, -vOFS=, '{
    $6=""
    if (length($2) == 0) { $6="+"; $2=$4; $3=$5; }
    else if (length($4) == 0) { $6="-"; }
    else { $2=$4; $3=$5; }
    print $6,$1,$2,$3
}'

मुझे एक अजीब एहसास है कि मैं दोनों फाइलों से data2 कॉलम को सुरक्षित रखूंगा, जैसा कि वे भिन्न हैं, और वास्तव में विचारों को सरल बनाते हैं, बस के साथ:

join -t, -11 -21  -a1 -a2 -o auto a.csv b.csv | 
awk -vFS=, -vOFS=, '{
    $6=""
    if (length($2) == 0) $6="+"
    if (length($4) == 0) $6="-"
    print $6,$1,$2,$3,$4,$5
}'

जो आउटपुट करता है:

-,1,A,B,,
,2,A,B,A,C
,3,A,B,A,C
,4,A,B,A,C
+,5,,,A,C

जिसकी व्याख्या इस प्रकार की जाती है:

# diff, id, data from a.csv, data2 from a.csv, data from b.csv, data2 from b.csv

लाइव संस्करण tutorialspoint पर उपलब्ध है।

0
KamilCuk 10 पद 2018, 21:21