Awk का उपयोग करते हुए, चर की संख्या के साथ फ़ाइल में पहले कॉलम की चौड़ाई को संशोधित करें


10

मैं समझता हूं कि awk के प्रिंटफ फ़ंक्शन का उपयोग कैसे करें, लेकिन मैं हर क्षेत्र को निर्दिष्ट नहीं करना चाहता।

उदाहरण के लिए, मान लें कि यह मेरी फ़ाइल है:

c1|c2|c3|c4|c5
c6|c7|c8|c9|c10
c11|c12|c13|c14|c15

मैं इसे प्रारूपित करना चाहता हूं ताकि हर रिकॉर्ड का पहला क्षेत्र c11 की चौड़ाई हो - पहले क्षेत्र में सबसे लंबी सेल:

c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15

मैं समझता हूं कि मैं निर्दिष्ट कर सकता हूं:

awk -F"|" '{printf "%-3s%s%s%s%s\n", $1, $2, $3, $4, $5}' file > newfile

आइए मान लें कि मुझे पता है कि मैं पहले कॉलम की चौड़ाई क्या चाहता हूं, लेकिन मुझे नहीं पता कि फ़ाइल में कितने फ़ील्ड हैं। मूल रूप से मैं कुछ ऐसा करना चाहता हूं:

... '{printf "%-3s|", $1}'

... और फिर बाकी क्षेत्रों को उनके मूल प्रारूप में प्रिंट करें।


इसे संबोधित करने का एक और तरीका: sed 's/|/'' '' '' |/;s/\(...\) */\1/'(यहाँ उन 3 स्थानों को जोड़ने के लिए अतिरिक्त उद्धरण जोड़ें जैसे कि एसई टिप्पणियाँ एक में सन्निहित रिक्त स्थान
निचोड़ते हैं

जवाबों:


14

आप केवल sprintfपुनः प्रारूप में उपयोग कर सकते हैं $1

पूर्व।

$ awk 'BEGIN{OFS=FS="|"} {$1 = sprintf("%-3s",$1)} 1' file
c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15

संक्षिप्त, आप awk -vf1=3 'BEGIN{OFS=FS="|"}{$1=sprintf("%-*s",f1,$1)}1' test.txt
स्प्रिंटफ के

@ A.Danischewski - खैर, खतरा। मैं ~ 17 वर्षों से व्यापक awk प्रोग्रामिंग कर रहा हूं, और इससे पहले कभी नहीं आया। सभी परेशानियों के बारे में सोचने के लिए इसने मुझे बचाया होगा।
पॉल सिनक्लेयर

6

पहले क्षेत्र की सबसे बड़ी / सबसे लंबी लंबाई का पता लगाने के लिए, और फिर उस लंबाई के अनुसार क्षेत्र में मूल्यों का सुधार करने के लिए, आपको फ़ाइल पर दो अलग-अलग पास करने होंगे।

awk 'BEGIN     { OFS = FS = "|" }
     FNR == NR { if (m < (n=length($1))) m = n; next }
               { $1 = sprintf("%-*s", m, $1); print }' file file

(ध्यान दें कि इनपुट फ़ाइल कमांड लाइन पर दो बार निर्दिष्ट की गई है)

आपके द्वारा प्रस्तुत डेटा के लिए, यह उत्पादन करेगा

c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15

पहला पास FNR == NRब्लॉक द्वारा संभाला जाता है , जो बस अब तक देखे गए सबसे लंबे क्षेत्र का ट्रैक रखता है ( mजिसमें अधिकतम लंबाई देखी गई है), और अगली पंक्ति तक जाती है।

दूसरा पास अंतिम ब्लॉक द्वारा संभाला जाता है, जो पहले क्षेत्र का उपयोग करके सुधार करता है sprintf()। प्रारूप स्ट्रिंग का %-*sअर्थ है "एक वाम-औचित्य स्ट्रिंग जिसकी चौड़ाई पूर्णांक तर्क द्वारा वास्तविक तर्क रखने वाले तर्क से पहले दी गई है"।

यह स्पष्ट रूप से स्केलर mको एक कॉलम में बदलकर सभी स्तंभों को करने के लिए विस्तारित किया जा सकता है जो प्रत्येक स्तंभ की अधिकतम चौड़ाई रखता है:

$ awk 'BEGIN     { OFS = FS = "|" }
       FNR == NR { for (i=1; i<=NF; ++i) if (m[i] < (n=length($i))) m[i] = n; next }
                 { for (i=1; i<=NF; ++i) $i = sprintf("%-*s", m[i], $i); print }' file file
c1 |c2 |c3 |c4 |c5
c6 |c7 |c8 |c9 |c10
c11|c12|c13|c14|c15

1

बुद्धिमान तरीका यह है कि स्टीलड्राइवर ने क्या सुझाव दिया । अनावश्यक रूप से जटिल तरीका यह है कि हर क्षेत्र में पुनरावृति हो:

$ awk -F'|' '{printf "%-3s|",$1; for(i=2;i<NF;i++){printf "%s|",$i} printf "%s\n", $i}' file
c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15

लेकिन बस sprintf $1और इसके साथ किया जाना चाहिए।


1
आप इसे थोड़ा पीछे की ओर ले गए हैं, छोटे संक्षिप्त बयान आम तौर पर अधिक जटिल होते हैं। खेतों के ऊपर कटाई कम जटिल है।
ए। डिस्केवस्की

1

Awk में आप एक "*" का उपयोग करके एक गतिशील प्रिंटफ प्रारूप स्ट्रिंग उत्पन्न कर सकते हैं।

यदि आप लंबाई पहले से ही जानते हैं, तो आप पहले कॉलम के लिए फ़ील्ड लंबाई -v के साथ पास कर सकते हैं।

awk -vcol1=3 'BEGIN{FS="|"}{for(i=1;i<=NF;i++){if(i==1)printf "%*-s%s",col1,$i,FS;else if(i!=NF)printf "%s%s",$i,FS;else printf "%s\n",$i;};}' test.txt

ध्यान दें: यदि आपको नहीं पता था कि आप पहली कॉलम की लंबाई क्या है, तो आप किसी ऐरे में मान स्टोर कर सकते हैं और अधिकतम कोल लेंथ को रास्ते में पा सकते हैं और इसे सभी ब्लॉक में प्रिंट कर सकते हैं।

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