निर्धारित करें कि एक पंक्ति में कितने लंबे टैब हैं


10

एक टेक्स्ट प्रोसेसिंग फील्ड में यह जानने का एक तरीका है कि क्या एक टैब लंबाई में 8 वर्ण (डिफ़ॉल्ट लंबाई) या कम है?

उदाहरण के लिए, यदि मेरे पास टैब सीमांकक के साथ एक नमूना फ़ाइल है और एक फ़ील्ड की सामग्री एक टैब (if7) से कम में फिट है, और अगर मेरे पास एक टैब है, तो वह टैब केवल 'टैब आकार - फ़ील्ड आकार होगा ' लंबाई में।

क्या एक लाइन पर टैब की कुल लंबाई प्राप्त करने का एक तरीका है? मैं टैब की संख्या नहीं ढूंढ रहा (यानी 10 टैब को 10 नहीं लौटाना चाहिए) लेकिन उन टैब की वर्ण लंबाई।

निम्नलिखित इनपुट डेटा के लिए (फ़ील्ड और केवल एक टैब के बीच सीमांकित टैब):

field0  field00 field000        last-field
fld1    fld11   fld001  last-fld
fd2     fld3    last-fld

मुझे प्रत्येक पंक्ति में टैब की लंबाई गिनने की उम्मीद है, इसलिए

11
9
9

जवाबों:


22

TABचरित्र एक नियंत्रण चरित्र है जो जब एक terminal¹ के लिए भेजा अगले टैब-ठहराव के लिए टर्मिनल के कर्सर चाल बनाता है। डिफ़ॉल्ट रूप से, अधिकांश टर्मिनलों में, टैब स्टॉप 8 कॉलम से अलग होते हैं, लेकिन यह कॉन्फ़िगर करने योग्य है।

आप अनियमित अंतराल पर टैब स्टॉप भी कर सकते हैं:

$ tabs 3 9 11; printf '\tx\ty\tz\n'
  x     y z

केवल टर्मिनल जानता है कि एक TAB दायीं ओर कितने कॉलम कर्सर को ले जाएगा।

आप टैब से पहले और बाद में टर्मिनल से कर्सर की स्थिति के बारे में पूछकर वह जानकारी प्राप्त कर सकते हैं।

यदि आप किसी दिए गए लाइन के लिए उस गणना को हाथ से बनाना चाहते हैं और यह मानकर कि लाइन स्क्रीन के पहले कॉलम में छपी है, तो आपको निम्न की आवश्यकता होगी:

  • पता है कि टैब-स्टॉप कहां हैं?
  • हर चरित्र की प्रदर्शन चौड़ाई जानते हैं
  • स्क्रीन की चौड़ाई जानते हैं
  • तय करें कि आप अन्य नियंत्रण वर्णों को संभालना चाहते हैं जैसे \r(जो कर्सर को पहले कॉलम में \bले जाता है ) या जो कर्सर को पीछे ले जाता है ...)

इसे सरल किया जा सकता है यदि आप मान लें कि टैब स्टॉप्स हर 8 कॉलम हैं, तो लाइन स्क्रीन में फिट होती है और कोई अन्य नियंत्रण वर्ण या वर्ण (या गैर-वर्ण) नहीं हैं जो आपका टर्मिनल ठीक से प्रदर्शित नहीं कर सकता है।

GNU के साथ wc, यदि लाइन में संग्रहीत किया जाता है $line:

width=$(printf %s "$line" | wc -L)
width_without_tabs=$(printf %s "$line" | tr -d '\t' | wc -L)
width_of_tabs=$((width - width_without_tabs))

wc -Lअपने इनपुट में सबसे चौड़ी लाइन की चौड़ाई देता है। ऐसा लगता है कि wcwidth(3)वर्णों की चौड़ाई निर्धारित करने और टैब स्टॉप्स का उपयोग करने से प्रत्येक 8 कॉलम हैं।

गैर-जीएनयू प्रणालियों के लिए, और समान मान्यताओं के साथ, @ कुसलानंद का दृष्टिकोण देखें । यह और भी बेहतर है क्योंकि यह आपको टैब स्टॉप को निर्दिष्ट करने देता है लेकिन दुर्भाग्य से वर्तमान में GNU expand(कम से कम) के साथ काम नहीं करता है जब इनपुट में मल्टी-बाइट वर्ण या 0-चौड़ाई (जैसे वर्णों को मिलाकर) या दोहरे-चौड़ाई वाले वर्ण होते हैं।


¹ ध्यान दें कि यदि आप ऐसा करते हैं stty tab3, तो tty डिवाइस लाइन अनुशासन टैब प्रोसेसिंग को ले लेगा (TAB को अपने स्वयं के विचार के आधार पर रिक्त स्थान में परिवर्तित करें जहां कर्सर टर्मिनल पर भेजने से पहले हो सकता है) और टैब को लागू करने से प्रत्येक 8 कॉलम बंद हो जाता है। लिनक्स पर परीक्षण, यह ठीक से सीआर, एलएफ और बीएस वर्णों के साथ-साथ मल्टीबैट यूटीएफ -8 वाले (प्रदान iutf8की गई है) को संभालने के लिए लगता है ( लेकिन यह भी इसके बारे में है)। यह मानता है कि अन्य सभी गैर-नियंत्रण वर्ण (शून्य-चौड़ाई, दोहरे-चौड़ाई वाले वर्णों सहित) की चौड़ाई 1 है, यह (स्पष्ट रूप से) बच अनुक्रमों को संभालता नहीं है, ठीक से लपेटता नहीं है ... शायद यह टर्मिनलों के लिए अभिप्रेत है टैब प्रसंस्करण नहीं कर सकता।

किसी भी स्थिति में, ट्टी लाइन अनुशासन को यह जानना आवश्यक है कि कर्सर कहाँ है और ऊपर दिए गए उन आंकड़ों का उपयोग करता है, क्योंकि icanonलाइन एडिटर का उपयोग करते समय (जैसे जब आप अनुप्रयोगों के लिए पाठ दर्ज करते हैं जैसे catकि अपने स्वयं के लाइन संपादक को लागू नहीं करते हैं), जब आप प्रेस TabBackspace, लाइन अनुशासन को यह जानने की जरूरत है कि प्रदर्शन के लिए उस टैब चरित्र को मिटाने के लिए कितने बीएस वर्ण भेजने हैं। यदि आप बदलते हैं कि टैब कहां है (जैसे tabs 12), तो आप देखेंगे कि टैब ठीक से मिटाए नहीं गए हैं। यदि आप दबाने से पहले डबल-चौड़ाई वाले अक्षर दर्ज करते हैं तो भी TabBackspace


You इसके लिए, आप टैब वर्ण भेज सकते हैं और प्रत्येक के बाद कर्सर की स्थिति को क्वेरी कर सकते हैं। कुछ इस तरह:

tabs=$(
  saved_settings=$(stty -g)
  stty -icanon min 1 time 0 -echo
  gawk -vRS=R -F';' -vORS= < /dev/tty '
    function out(s) {print s > "/dev/tty"; fflush("/dev/tty")}
    BEGIN{out("\r\t\33[6n")}
    $NF <= prev {out("\r"); exit}
    {print sep ($NF - 1); sep=","; prev = $NF; out("\t\33[6n")}'
  stty "$saved_settings"
)

उसके बाद, आप expand -t "$tabs"कुसलानंद के समाधान का उपयोग कर सकते हैं।


7
$ expand file | awk '{ print gsub(/ /, " ") }'
11
9
9

POSIX expandउपयोगिता रिक्त स्थान के लिए टैब का विस्तार करती है। awkस्क्रिप्ट मायने रखता है और आउटपुट प्रत्येक पंक्ति पर सभी रिक्त स्थान को बदलने के लिए की जरूरत प्रतिस्थापन की संख्या।

इनपुट फ़ाइल में किसी भी preexisting रिक्त स्थान की गिनती से बचने के लिए:

$ tr ' ' '@' <file | expand | awk '{ print gsub(/ /, " ") }'

जहां @एक चरित्र है कि इनपुट डेटा में मौजूद नहीं गारंटी है है।

यदि आप साधारण 8 के बजाय प्रति टैब 10 स्थान चाहते हैं:

$ tr ' ' '@' <file | expand -t 10 | awk '{ print gsub(/ /, " ") }'
9 
15
13

3
आप अन्यथा xकॉल करने से पहले कुछ अन्य एक-चौड़ाई वाले चरित्र (जैसे ) के साथ रिक्त स्थान बदलना चाहते हैं expand, आप उन रिक्त स्थान की भी गणना करेंगे जो शुरू में इनपुट में भी थे।
स्टीफन चेज़लस

1
expandप्रत्येक 8 कॉलमों को टैब-स्टॉप भी मानता है (हालांकि आप विकल्पों के साथ इसे बदल सकते हैं)। ध्यान दें कि GNU कार्यान्वयन मल्टी-बाइट वर्णों का समर्थन नहीं करता है (अकेले 0-चौड़ाई या डबल-चौड़ाई वाले)। IIRC फ्रीबीएसडी एक ठीक है।
स्टीफन चेज़लस

@ स्टीफनचेज़लस अनलेस, निश्चित रूप से, यह 0x20s ;-) के साथ 0x09s की चौड़ाई को गिनने की योजना का हिस्सा है ;-)
can-ned_food

2

के साथ perl:

perl -F/\\t/ -lpe '$c = 0; $F[-1] eq "" or pop @F; $_ = (map { $c += 8 - (length) % 8 } @F)[-1]' file

वैकल्पिक रूप से:

perl -MList::Util=reduce -lpe \
    '@F = split /\t/, $_, -1; pop @F if $F[-1] ne ""; $_ = reduce { $a + $b } map { 8 - (length) % 8 } @F' file

यदि आप चाहते हैं कि TABs की लंबाई अलग हो, तो आप कुछ अन्य मान के साथ 8 को बदल सकते हैं।


2

expandरिक्त स्थान की संख्या की गणना करने के लिए बैश पैरामीटर हेरफेर के साथ भी , उपयोग करना:

$ line=$'field0\tfield00\tfield000\tlast-field'
$ tabs2spaces=$(expand <<<"$line")
$ only_spaces=${tabs2spaces//[^ ]/}    # remove all non-space characters
$ echo "${#only_spaces}"
11
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.