पंक्तियों और स्तंभों को स्थानांतरित करना


18

मेरे पास नीचे की तरह लाइनों के साथ एक फ़ाइल है।

title1:A1
title2:A2
title3:A3
title4:A4
title5:A5

title1:B1
title2:B2
title3:B3
title4:B4
title5:B5

title1:C1
title2:C2
title3:C3
title4:C4
title5:C5

title1:D1
title2:D2
title3:D3
title4:D4
title5:D5

इसे कैसे प्राप्त किया जा सकता है?

title1    title2     title3    title4
A1         A2         A3         A4
B1         B2         B3         B4
C1         C2         C3         C4
D1         D2         D3         D4


कृप्या प्लीज प्लीज यूज न करें, आप कस्टम या पर्ल या पाइथन या वास्तविक प्रोग्रामिंग लैंग्वेज के साथ कस्टम सॉल्यूशन को रोल कर सकते हैं या आप जो चाहते हैं उसे पाने के लिए कई पास के साथ tr / cut का इस्तेमाल कर सकते हैं
रुडोल्फ ओलह

जवाबों:



9

एक कमांड लाइन से स्तंभों के साथ पंक्तियों को स्थानांतरित करने के लिए एक कस्टम समाधान को रोल करने के बाहर एकमात्र उपकरण जो मैंने कभी देखा है कि ऐसा कर सकते हैं यह विडंबनापूर्ण रूप से एक उपकरण है transpose

स्थापना

दुर्भाग्य से यह किसी भी रेपो में नहीं है इसलिए आपको इसे डाउनलोड करने और संकलित करने की आवश्यकता होगी। यह बहुत सीधा है क्योंकि इसमें कोई अतिरिक्त लाइब्रेरी नहीं है जो इस पर निर्भर है। इसे इस तरह पूरा किया जा सकता है:

$ gcc transpose.c -o transpose

प्रयोग

यह आसानी से सरल पाठ फ़ाइलों को संभाल सकता है। उदाहरण के लिए:

$ cat simple.txt 
X column1 column2 column3
row1 0 1 2
row2 3 4 5
row3 6 7 8
row4 9 10 11

इस आदेश का उपयोग करके ट्रांसपोज़ किया जा सकता है:

$ transpose -t --fsep " " simple.txt 
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11

यह कमांड transposeट्रांसपोज़ करना है ( -t) और उपयोग करने के लिए फील्ड सेपरेटर एक स्पेस ( --fsep " ") है।

आपका उदाहरण

चूंकि आपका नमूना डेटा कुछ अधिक जटिल प्रारूप में है, इसलिए इसे 2 चरणों में निपटाया जाना चाहिए। पहले हमें इसे एक ऐसे प्रारूप में अनुवाद करना होगा जो इससे transposeनिपट सकता है।

इस आदेश को चलाने से, डेटा को अधिक क्षैतिज रूप से अनुकूल प्रारूप में रखा जाएगा:

$ sed 's/:/ /; /^$/d' sample.txt \
    | sort | paste - - - - -
title1 A1   title1 B1   title1 C1   title1 D1   title2 A2
title2 B2   title2 C2   title2 D2   title3 A3   title3 B3
title3 C3   title3 D3   title4 A4   title4 B4   title4 C4
title4 D4   title5 A5   title5 B5   title5 C5   title5 D5

अब हमें सिर्फ title1, title2, आदि की द्वितीयक घटनाओं को हटाने की आवश्यकता है:

$ sed 's/:/ /; /^$/d' sample.txt \
    | sort | paste - - - - - | sed 's/\ttitle[0-9] / /g'
title1 A1 B1 C1 D1 A2
title2 B2 C2 D2 A3 B3
title3 C3 D3 A4 B4 C4
title4 D4 A5 B5 C5 D5

यह अब एक प्रारूप में है जो इससे transposeनिपट सकता है। निम्नलिखित आदेश संपूर्ण ट्रांसपोज़ेशन करेगा:

$ sed 's/:/ /; /^$/d' sample.txt \
    | sort | paste - - - - - | sed 's/\ttitle[0-9] / /g' \
    | transpose -t --fsep " "
title1 title2 title3 title4
A1 B2 C3 D4
B1 C2 D3 A5
C1 D2 A4 B5
D1 A3 B4 C5
A2 B3 C4 D5

8

आप awkतब डेटा को संसाधित करने pasteऔर columnउसे प्रारूपित करने के लिए उपयोग कर सकते हैं ।

यहाँ मैं मानता हूँ कि title1आपके पोस्ट में केवल एक उदाहरण है, और उस डेटा में :हेडर + डेटा के बीच विभाजक के अलावा शामिल नहीं है ।

nयह दर्शाता है कि कितने कॉलम प्रिंट करने चाहिए (डैश से मेल खाने चाहिए paste)।

awk -F":" -v n=4 \
'BEGIN { x=1; c=0;} 
 ++c <= n && x == 1 {print $1; buf = buf $2 "\n";
     if(c == n) {x = 2; printf buf} next;}
 !/./{c=0;next}
 c <=n {printf "%s\n", $2}' datafile | \
 paste - - - - | \
 column -t -s "$(printf "\t")"

यदि आप इसे अधिक लचीला और आसान बनाना चाहते हैं तो आप इसे स्क्रिप्ट के रूप में लिख सकते हैं। यहाँ एक उदाहरण के लिए बैश रैपर का उपयोग किया गया है awkऔर इसके लिए पाइप किया गया है column। इस तरह आप अधिक डेटा जाँच भी कर सकते हैं जैसे कि यह सुनिश्चित करना कि हेडर सभी पंक्तियों आदि में सही है।

आमतौर पर इस्तेमाल के रूप में:

$ ./trans -f data -c 4
title one  title two  title three  title four
A1         A2         A3           A4
B1         B2         B3           B4
C1         C2         C3           C4
D1         D2         D3           D4

हेडर हमेशा छोटे फिर जो डेटा आप भी हैडर चौड़ाई को बचाने, तो कर सकते थे तो printfसाथ %-*sऔर छोड़ columnसब एक साथ।

#!/bin/bash

trans()
{
    awk -F":" -v ncol="$1" '
    BEGIN {
        level = 1 # Run-level.
        col   = 1 # Current column.
        short = 0 # If requested to many columns.
    }
    # Save headers and data for row one.
    level == 1 {
        head[col] = $1
        data[col] = $2
        if (++col > ncol) { # We have number of requested columns.
            level = 2
        } else if ($0 == "") { # If request for more columns then available.
            level = 2
            ncol  = col - 2
            short = 1
        } else {
            next
        }
    }
    # Print headers and row one.
    level == 2 {
        for (i = 1; i <= ncol; ++i)
            printf("%s\t", head[i])
        print ""
        for (i = 1; i <= ncol; ++i)
            printf("%s\t", data[i])
        level = 3
        col = ncol + 1
        if (!short)
            next
    }
    # Empty line, new row.
    ! /./ { print ""; col = 1; next }
    # Next cell.
    col > ncol {next}
    {
        printf "%s%s", $2, (col <= ncol) ? "\t" : ""
        ++col
    }
    END {print ""}
    ' "$2"
}

declare -i ncol=4  # Columns defaults to four.
file=""            # Data file (or pipe).

while [[ -n "$1" ]]; do
    case "$1" in
    "-c") ncol="$2"; shift;;
    "-f") file="$2"; shift;;
    *) printf "Usage: %s [-c <columns>] [-f <file> | pipe]\n" \
        "$(basename $0)" >&2;
        exit;;
    esac
    shift
done

trans "$ncol" "$file" | column -t -s "$(printf "\t")"

1
अच्छा उत्तर! @JoelDavis और मैं इस पर हैकिंग कर रहे हैं, लेकिन आपका जवाब बहुत अच्छा है!
स्लम

7

फ़ाइल को उस प्रारूप में रखने का एक त्वरित तरीका है जो आप चाहते हैं:

$ grep -Ev "^$|title5" sample.txt | sed 's/title[0-9]://g' | paste - - - -
A1  A2  A3  A4
B1  B2  B3  B4
C1  C2  C3  C4
D1  D2  D3  D4

यदि आप कॉलम हेडर चाहते हैं:

$ grep -Ev "^$|title5" sample.txt | sed 's/:.*//' | sort -u | tr '\n' '\t'; \
    echo ""; \
    grep -Ev "^$|title5" a | sed 's/title[0-9]://g' | paste - - - -
title1  title2  title3  title4  
A1      A2      A3      A4
B1      B2      B3      B4
C1      C2      C3      C4
D1      D2      D3      D4

दूसरा कमांड कैसे काम करता है

बैनर छापना
grep -Ev "^$|title5" sample.txt | sed 's/:.*//' | sort -u | tr '\n' '\t';
में बैनर के बाद एक वापसी डाल
echo
डेटा की पंक्तियों को मुद्रित करना
grep -Ev "^$|title5" a | sed 's/title[0-9]://g' | paste - - - -

पेस्ट कमांड ने बस मेरा काम कर दिया। उत्तर के लिए धन्यवाद ...
SK वेंकट


3

इसे तैयार करने का शायद अधिक सफल तरीका है, लेकिन यह सामान्य प्रभाव को पूरा करता है:

[jadavis84@localhost ~]$ sed 's/^title[2-9]://g' file.txt | tr '\n' '\t' | sed 's/title1:/\n/g' ; echo

A1  A2  A3  A4  A5      
B1  B2  B3  B4  B5      
C1  C2  C3  C4  C5      
D1  D2  D3  D4  D5  
[jadavis84@localhost ~]$ 

मल्टीपल sedइनवोकेशन सही नहीं लगता (और मुझे पूरा यकीन है कि sed नई लाइन ट्रांसलेशन भी कर सकता है) इसलिए यह शायद इसे करने का सबसे सीधा तरीका नहीं है। इसके अलावा, यह हेडर हो सकता है, लेकिन आप पंक्तियों / फ़ील्ड्स को ठीक से स्वरूपित करने के बाद मैन्युअल रूप से उत्पन्न कर सकते हैं।

एक बेहतर जवाब शायद उस प्रभाव को बिगाड़ देगा जिसका उपयोग सिर्फ करने के लिए sedया awkऐसा करने के लिए किया गया है ताकि आपके पास एक समय में केवल एक चीज हो। लेकिन मैं थका हुआ हूं इसलिए यह वही है जो मैं एक साथ करने में सक्षम था।


जोएल - मैंने वही गलती की और सिर्फ इस पर ध्यान दिया, वह आउटपुट में शीर्षक 5 कॉलम नहीं चाहता है।
स्लम

आह, आखिरी में जाग के माध्यम से अच्छी तरह से चल रहा है कि ठीक करना चाहिए। लेकिन ऐसा लग रहा है कि सुक्मिंदर ने एक पूरा समाधान पोस्ट किया है।
ब्राचली

1

pasteशायद तुम्हारा सबसे अच्छा दांव है। आप के साथ प्रासंगिक बिट निकाल सकते हैं cut, grepऔर awkयह पसंद:

(awk 'NR==1' RS= infile | cut -d: -f1; cut -sd: -f2 infile)

यदि 5 वें कॉलम को समाप्त किया जाना चाहिए, तो awk 'NR%5'इस तरह संलग्न करें:

(awk 'NR==1' RS= infile | cut -d: -f1; cut -sd: -f2 infile) | awk 'NR%5'

अब इसके साथ कॉलम करें paste:

(awk 'NR==1' RS= infile | cut -d: -f1; cut -sd: -f2 infile) | awk 'NR%5' | paste - - - -

आउटपुट:

title1  title2  title3  title4
A1  A2  A3  A4
B1  B2  B3  B4
C1  C2  C3  C4
D1  D2  D3  D4

0

हाल ही में बदले हुए भाग के लिए, मुझे हाल ही में एक समान समस्या हुई थी और इसका इस्तेमाल किया गया था:

awk -v fmt='\t%4s'  '{ for(i=1;i<=NF;i++){ a[i]=a[i] sprintf(fmt, $i); } } END { for (i in a) print a[i]; }'

आवश्यकतानुसार fmt को समायोजित करें। प्रत्येक इनपुट लाइन के लिए, यह प्रत्येक फ़ील्ड को एक एलीमेंट एलीमेंट पर समेटता है। ध्यान दें कि awk string concatenation निहित है: यह तब होता है जब आप बिना किसी ऑपरेटर के दो चीजें लिखते हैं।

नमूना I / O:

i       mark    accep   igna    utaal   bta
-22     -10     -10     -20     -10     -10
-21     -10     -10     -20     -10     -10
-20     -10     -10     -20     -10     -10
-19     -10     0       -10     -10     -10
-18     0       0       -10     0       0
-12     0       0       -10     0       0
-11     0       0       -10     0       0
-10     0       0       -10     0       0

उत्पादन:

       i     -22     -21     -20     -19     -18     -12     -11     -10
    mark     -10     -10     -10     -10       0       0       0       0
    accep    -10     -10     -10       0       0       0       0       0
    igna     -20     -20     -20     -10     -10     -10     -10     -10
    utaal    -10     -10     -10     -10       0       0       0       0
     bta     -10     -10     -10     -10       0       0       0       0

-1

सबसे आसान काम जो आप cutखेतों को काटने के लिए कर सकते हैं और फिर उपयोग trकर सकते हैं यदि आप पंक्तियों को कॉलम में नई वर्ण रेखा को टैब वर्ण से बदलकर उपयोग कर रहे हैं: http://www.gnu.org/software/coreutils/manual/ coreutils.html # tR-मंगलाचरण

cat file.txt | cut -d':' | tr '\n' '\t'

फ़ील्ड की सूची के बिना, cutएक त्रुटि देता है।
एजीसी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.