पंक्तियों को कॉलम में बदलें


10

मेरे पास एक फाइल है जिसमें एक हाइपरविजर में चल रहे VMs के बारे में विवरण शामिल है। हम कुछ कमांड चलाते हैं और आउटपुट को एक फाइल पर रीडायरेक्ट करते हैं। और डेटा नीचे प्रारूप में उपलब्ध है।

Virtual Machine : OL6U5
        ID     : 0004fb00000600003da8ce6948c441bb
        Status : Running
        Memory : 65536
        Uptime : 17835 Minutes
        Server : MyOVS1.vmorld.com
        Pool   : HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6
Virtual Machine : OL6U6
        ID     : 0004fb00000600003da8ce6948c441bc
        Status : Running
        Memory : 65536
        Uptime : 17565 Minutes
        Server : MyOVS2.vmorld.com
        Pool   : NON-HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6
Virtual Machine : OL6U7
        ID     : 0004fb00000600003da8ce6948c441bd
        Status : Running
        Memory : 65536
        Uptime : 17835 Minutes
        Server : MyOVS1.vmorld.com
        Pool   : HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6

यह आउटपुट हाइपरविज़र से हाइपरवाइज़र तक भिन्न होता है क्योंकि कुछ हाइपरविज़र पर हमारे पास 50 + vms चल रहा है। उपरोक्त फ़ाइल हाइपरविज़र का एक उदाहरण है, जहाँ हमारे पास केवल 3 VM चल रहे हैं और इसलिए पुनर्निर्देशित फ़ाइल में कई (VM की संख्या N) के बारे में जानकारी होने की उम्मीद है

हमें यह विवरण नीचे दिए गए प्रारूप में awk / sed या शेल स्क्रिप्ट के साथ प्राप्त करने की आवश्यकता है

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool        HA     VCPU  Type     OS
OL6U5            0004fb00000600003da8ce6948c441bb  Running  65536   17835   MyOVS1.vmworld.com  HA-POOL     false  16    Xen PVM  Oracle Linux 6
OL6U6            0004fb00000600003da8ce6948c441bc  Running  65536   17565   MyOVS2.vmworld.com  NON-HA-POOL     false  16    Xen PVM  Oracle Linux 6
OL6U5            0004fb00000600003da8ce6948c441bd  Running  65536   17835   MyOVS1.vmworld.com  HA-POOL     false  16    Xen PVM  Oracle Linux 6

जवाबों:


1

यदि फ़ाइल को दो बार चलना एक (बड़ी) समस्या नहीं है (मेमोरी में केवल एक लाइन स्टोर करेगा):

awk -F : '{printf("%s\t ", $1)}' infile
echo
awk -F : '{printf("%s\t ", $2)}' infile

जो, खेतों की एक सामान्य गणना के लिए होगा (जो फ़ाइल के कई हिस्से हो सकते हैं):

#!/bin/bash
rowcount=2
for (( i=1; i<=rowcount; i++ )); do
    awk -v i="$i" -F : '{printf("%s\t ", $i)}' infile
    echo
done

लेकिन वास्तव में सामान्य बदलाव के लिए, यह काम करेगा:

awk '$0!~/^$/{    i++;
                  split($0,arr,":");
                  for (j in arr) {
                      out[i,j]=arr[j];
                      if (maxr<j){ maxr=j} # max number of output rows.
                  }
            }
    END {
        maxc=i                             # max number of output columns.
        for     (j=1; j<=maxr; j++) {
            for (i=1; i<=maxc; i++) {
                printf( "%s\t", out[i,j])  # out field separator.
            }
            printf( "%s\n","" )
        }
    }' infile

और इसे सुंदर बनाने के लिए ( \tफ़ील्ड सेपरेटर के रूप में टैब का उपयोग करके ):

./script | |column -t -s $'\t'

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool     HA     VCPU  Type     OS
OL6U7            0004fb00000600003da8ce6948c441bd  Running  65536   17103   MyOVS1.vmworld.com  HA-POOL  false  16    Xen PVM  Oracle Linux 6

एक सामान्य स्थानान्तरण के लिए उपरोक्त कोड मेमोरी में पूरे मैट्रिक्स को स्टोर करेगा।
यह वास्तव में बड़ी फ़ाइलों के लिए एक समस्या हो सकती है।


नए पाठ के लिए अद्यतन।

प्रश्न में पोस्ट किए गए नए पाठ को संसाधित करने के लिए, यह मुझे लगता है कि awk के दो पास सबसे अच्छा उत्तर हैं। एक पास, जहां तक ​​फ़ील्ड मौजूद हैं, हेडर फ़ील्ड शीर्षक प्रिंट करेगा। अगला awk पास केवल फ़ील्ड 2 को प्रिंट करेगा। दोनों ही मामलों में, मैंने अग्रणी और अनुगामी रिक्त स्थान (बेहतर स्वरूपण के लिए) को निकालने का एक तरीका जोड़ा।

#!/bin/bash
{
awk -F: 'BEGIN{ sl="Virtual Machine"}
         $1~sl && head == 1 { head=0; exit 0}
         $1~sl && head == 0 { head=1; }
         head == 1 {
             gsub(/^[ \t]+/,"",$1);   # remove leading  spaces
             gsub(/[ \t]+$/,"",$1);   # remove trailing spaces
             printf( "%s\t", $1)
         }
         ' infile
#echo
awk -F: 'BEGIN { sl="Virtual Machine"}
         $1~sl { printf( "%s\n", "") }
         {
             gsub(/^[ \t]+/,"",$2);   # remove leading  spaces
             gsub(/[ \t]+$/,"",$2);   # remove trailing spaces
             printf( "%s\t", $2)
         }
         ' infile
echo
} | column -t -s "$(printf '%b' '\t')"

आसपास { ... } | column -t -s "$(printf '%b' '\t')"पूरी तालिका को एक सुंदर तरीके से प्रारूपित करना है।
कृपया ध्यान दें कि ksh, bash, या zsh के "$(printf '%b' '\t')"साथ प्रतिस्थापित किया जा सकता है $'\t'


8

यदि आपके पास rs(रीसेट) उपयोगिता उपलब्ध है, तो आप निम्न कार्य कर सकते हैं:

rs -Tzc: < input.txt

यह आउटपुट स्वरूप को प्रश्न में निर्दिष्ट के रूप में देता है, यहां तक ​​कि डायनेमिक कॉलम की चौड़ाई तक।

  • -T इनपुट डेटा स्थानांतरित करता है
  • -z प्रत्येक स्तंभ में अधिकतम से स्तंभों को उचित आकार देता है
  • -c: इनपुट क्षेत्र विभाजक के रूप में कोलन का उपयोग करता है

यह मनमाने ढंग से आकार की तालिकाओं के लिए काम करता है, जैसे:

$ echo "Name:Alice:Bob:Carol
Age:12:34:56
Eyecolour:Brown:Black:Blue" | rs -Tzc: 
Name   Age  Eyecolour
Alice  12   Brown
Bob    34   Black
Carol  56   Blue
$ 

rsOS X (और संभवतः अन्य BSD मशीनों) पर डिफ़ॉल्ट रूप से उपलब्ध है। इसे उबंटू (और डेबियन परिवार) के साथ स्थापित किया जा सकता है:

sudo apt-get install rs

6

संपादित करें: एक साधारण एक-लाइनर forलूप में आउटपुट पंक्तियों की किसी भी संख्या के लिए एक्स्टेंसिबल :

for ((i=1;i<=2;i++)); do cut -d: -f "$i" input | paste -sd: ; done | column -t -s:

मूल उत्तर:

आप bashप्रक्रिया प्रतिस्थापन के उपयोग से वन-लाइनर के रूप में ऐसा कर सकते हैं :

paste -sd: <(cut -d: -f1 input) <(cut -d: -f2 input) | column -t -s:

इसे बनाने का -sविकल्प pasteएक बार में प्रत्येक फ़ाइल को संभालता है। :में सीमांकक सेट pasteद्वारा "पकड़ा" है -sकरने के लिए विकल्प columnक्षेत्रों बनाकर अंत में बहुत ऊपर प्रारूप करने के लिए, लाइन अप।

cutदो प्रक्रिया प्रतिस्थापन में आदेश बाहर पहले क्षेत्र और दूसरे क्षेत्र में क्रमश: खींच।

इनपुट में रिक्त लाइनें हैं या नहीं, इससे कोई फर्क नहीं पड़ता, क्योंकि column -t -s:आउटपुट को साफ करेगा। (प्रश्न में निर्दिष्ट मूल इनपुट में रिक्त लाइनें थीं, लेकिन उन्हें तब से हटा दिया गया है। उपरोक्त आदेश रिक्त लाइनों की परवाह किए बिना काम करता है।)

इनपुट - उपरोक्त कमांड में "इनपुट" नामक फ़ाइल की सामग्री:

Virtual_Machine:OL6U7

ID:0004fb00000600003da8ce6948c441bd

Status:Running

Memory:65536

Uptime:17103

Server:MyOVS1.vmworld.com

Pool:HA-POOL

HA:false

VCPU:16

Type:Xen PVM

OS:Oracle Linux 6

आउटपुट:

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool     HA     VCPU  Type     OS
OL6U7            0004fb00000600003da8ce6948c441bd  Running  65536   17103   MyOVS1.vmworld.com  HA-POOL  false  16    Xen PVM  Oracle Linux 6

2
यह दो आउटपुट पंक्तियों के लिए काम करता है, लेकिन अधिक पंक्तियों के लिए यह बेपरवाह हो जाता है।

2

Awk का उपयोग करके, कुंजी और मान को संग्रहीत करें और अंत में उन्हें प्रिंट करें।

#!/usr/bin/awk -f
BEGIN {
  CNT=0
  FS=":"
}

{
  HDR[CNT]=$1;
  ENTRY[CNT]=$2;
  CNT++;
}

END {
  for (x = 0; x < CNT; x++)
    printf "%s\t",HDR[x]

  print""

  for (x = 0; x < CNT; x++)
    printf "%s\t",ENTRY[x]
  }

सिर्फ दौड़ awk -f ./script.awk ./input.txt


उत्तर को गतिशील बनाया। बस आवश्यकता है कि प्रति फ़ाइल केवल 1 वीएम मूल्य का डेटा हो।
जेकजो

1
declare -a COLS
declare -a DATA
while IFS=':' read -ra fields; do
   COLS+=("${fields[0]}")
   DATA+=("${fields[1]}")
done < <( cat /path/to/input.txt)

HEADER=""
DATA=""
for i in $(seq 0 $((${#fields[@]}-1)); do
    HEADER="${HEADER}${COLS[$i]} "
    DATA="${DATA}${COLS[$i]} "
done
echo $HEADER
echo $DATA

1

साथ gnu datamashऔर columnसे util-linux:

datamash -t: transpose <infile | column -t -s:

यह दो से अधिक स्तंभों के साथ काम करता है, लेकिन मानता है कि आपकी इनपुट फ़ाइल में कोई खाली लाइनें नहीं हैं; बीच में खाली लाइनों के साथ (जैसे आपके प्रारंभिक इनपुट नमूने में) आपको एक त्रुटि मिलेगी जैसे:

datamash: transpose input error: line 2 has 0 fields (previous lines had 2);

इससे बचने के लिए आपको प्रसंस्करण से पहले उन्हें निचोड़ना होगा datamash:

tr -s \\n <infile | datamash -t: transpose | column -t -s:

अन्यथा, इस विशेष मामले में (केवल दो कॉलम), साथ zshऔर समान column:

list=(${(f)"$(<infile)"})
printf %s\\n ${(j;:;)list[@]%:*} ${(j;:;)list[@]#*:} | column -t -s:

(${(f)"$(<infile)"})एक सरणी में लाइनों को पढ़ता है; ${(j;:;)list[@]%:*}(साथ जुड़ जाता है :) प्रत्येक तत्व के पहले क्षेत्र और ${(j;:;)list[@]#*:}(फिर से साथ जुड़ जाता है :) प्रत्येक तत्व के दूसरे क्षेत्र; ये दोनों मुद्रित हैं, उदाहरण के लिए आउटपुट है

Virtual_Machine:ID:Status:Memory:Uptime:Server:Pool:HA:VCPU:Type:OS
OL6U7:0004fb00000600003da8ce6948c441bd:Running:65536:17103:MyOVS1.vmworld.com:HA-POOL:false:16:Xen PVM:Oracle Linux 6

जिसे तब पाइप किया जाता है column -t -s:


0

cat <(head -n 11 virtual.txt | cut -d: -f1) <(sed 's/.*: //' virtual.txt) | xargs -d '\n' -n 11 | column -t

वर्चुअल मशीन प्रति लाइन्स की संख्या इस मामले में हार्डकोडेड है - 11. पहले से इसे गिनना बेहतर होगा और वेरिएबल में स्टोर करना होगा, फिर कोड में इस वेरिएबल का उपयोग करें।

व्याख्या

  1. cat <(command 1) <(command 2)- <()निर्माण commandएक अस्थायी फ़ाइल की तरह दिखने वाले आउटपुट को बनाता है । इसलिए, catदो फ़ाइलों को संक्षिप्त करता है और इसे आगे पाइप करता है।

    • कमांड 1 :, head -n 11 virtual.txt | cut -d: -f1हमें भविष्य के कॉलम हेडर देता है। एक वर्चुअल मशीन प्रविष्टि पहले ग्यारह लाइनें है, headइसे प्राप्त करने के लिए कमांड का उपयोग किया जाता है। cutदो कॉलम को यह प्रविष्टि विभाजन और केवल पहले एक मुद्रित करें।
    • कमांड 2 : sed 's/.*: //' virtual.txt- हमें भविष्य के कॉलम मान देता है। sedसभी अनावश्यक पाठ हटाता है और केवल मान छोड़ता है।
  2. xargs -d '\n' -n 11। प्रत्येक इनपुट आइटम को newline द्वारा समाप्त किया जाता है। यह आदेश आइटम प्राप्त करता है और उन्हें 11 प्रति पंक्ति प्रिंट करता है।

  3. column -t- सुंदर प्रिंटिंग डिस्प्ले के लिए आवश्यक है। यह एक टेबल के रूप में हमारी लाइनों को प्रदर्शित करता है। अन्यथा, प्रत्येक पंक्ति अलग चौड़ाई होगी।

उत्पादन

Virtual  Machine                           ID       Status  Memory  Uptime   Server             Pool         HA     Mode  VCPU  Type  OS
OL6U5    0004fb00000600003da8ce6948c441bb  Running  65536   17835   Minutes  MyOVS1.vmorld.com  HA-POOL      false  16    Xen   PVM   Oracle  Linux  6
OL6U6    0004fb00000600003da8ce6948c441bc  Running  65536   17565   Minutes  MyOVS2.vmorld.com  NON-HA-POOL  false  16    Xen   PVM   Oracle  Linux  6
OL6U7    0004fb00000600003da8ce6948c441bd  Running  65536   17835   Minutes  MyOVS1.vmorld.com  HA-POOL      false  16    Xen   PVM   Oracle  Linux  6

0

किसी फ़ाइल में पंक्तियों और स्तंभों को स्वैप करने के लिए datamashइसके transposeविकल्प का उपयोग करें ।

datamash -t: transpose < infile.txt

डिफ़ॉल्ट रूप से, ट्रांज़ोज़ सत्यापित करता है कि इनपुट में प्रत्येक पंक्ति में समान फ़ील्ड हैं, और अन्यथा एक त्रुटि के साथ विफल हो जाता है और आप लापता मानों की अनुमति देने के लिए इसके सख्त मोड को अक्षम कर सकते हैं --no-strict

datamash -t: --no-strict transpose < infile.txt

इसके अलावा, आप --fillerअनुपलब्ध फ़ील्ड फिलर मान सेट करने के लिए उपयोग कर सकते हैं :

datamash -t: --no-strict --filler " " transpose < infile.txt

से व्युत्पन्न datamash manual


-5

यदि आपका डेटा किसी निर्देशिका में अलग-अलग फ़ाइलों में है, तो आप इसका उपयोग कर सकते हैं:

for file in $(ls $DIRECTORY)
do
  cat ${file} | while read line
  do
    value=$(echo $line | cut -d: -f2-)
    printf "%s\t" "${value}" >> bigfile
  done
  echo " " >> bigfile
done

यदि आपके चर मान अलग-अलग लंबाई के हैं, तो आपको लाइन \tपर (टैब) वर्णों की मालिश करने की आवश्यकता हो सकती है printf

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