मैं कुछ आउटपुट की प्रत्येक पंक्ति से व्हाट्सएप को अग्रणी और अनुगामी कैसे ट्रिम कर सकता हूं?


153

मैं एक आउटपुट में सभी प्रमुख और अनुगामी रिक्त स्थान और टैब को प्रत्येक पंक्ति से निकालना चाहूंगा।

वहाँ एक साधारण उपकरण की तरह trimमैं अपने उत्पादन में पाइप सकता है?

उदाहरण फ़ाइल:

test space at back 
 test space at front
TAB at end  
    TAB at front
sequence of some    space in the middle
some empty lines with differing TABS and spaces:





 test space at both ends 

1
किसी के लिए यहाँ देख के समाधान के लिए newlines, कि एक अलग समस्या है। परिभाषा के अनुसार एक नई पंक्ति पाठ की एक नई पंक्ति बनाती है। इसलिए पाठ की एक पंक्ति में एक नई रेखा नहीं हो सकती। जो प्रश्न आप पूछना चाहते हैं वह यह है कि एक स्ट्रिंग की शुरुआत या अंत से एक नई लाइन कैसे निकालें: stackoverflow.com/questions/369758 , या कैसे खाली लाइनों या लाइनों को हटाने के लिए जो सिर्फ व्हाट्सएप हैं: serverfault.com/questions/252921
टोनी

जवाबों:


198
awk '{$1=$1;print}'

या इससे कम:

awk '{$1=$1};1'

अग्रणी और अनुगामी स्थान या टैब वर्ण ट्रिम हैं 1 है और यह भी एक भी अंतरिक्ष में टैब और रिक्त स्थान के दृश्यों निचोड़।

यह काम करता है क्योंकि जब आप किसी एक फ़ील्ड में कुछ असाइन करते हैं , तो सभी फ़ील्ड ( , ..., ) को डिफ़ॉल्ट रूप से (स्पेस के साथ) awkजोड़कर पूरे रिकॉर्ड (जैसा कि मुद्रित होता है print) को पुन: बनाता है ।$1$NFOFS

1 (संभवत: स्थान और awkकार्यान्वयन के आधार पर अन्य रिक्त वर्ण )


2
दूसरे उदाहरण पर सेमीकॉलन शानदार है। उपयोग कर सकते हैं:awk '{$1=$1}1'
ब्रायन


दिलचस्प ... कोई अर्धविराम गॉक, मॉक और ओएस एक्स के जाग द्वारा समर्थित नहीं है। (कम से कम मेरे संस्करणों के लिए (1.2, 4.1.1, और 20070501, क्रमशः)
ब्रायन

1
केवल एक चीज जो मुझे इस दृष्टिकोण के बारे में पसंद नहीं है, वह यह है कि आप लाइन के भीतर दोहराए गए स्थान खो देते हैं। उदाहरण के लिए,echo -e 'foo \t bar' | awk '{$1=$1};1'
user.friendly

2
echo ' hello ' | xargs
JREAM

43

यदि आप GNU का उपयोग कर रहे हैं तो कमांड को संघनित किया जा सकता है sed:

$ sed 's/^[ \t]*//;s/[ \t]*$//' < file

उदाहरण

यहाँ ऊपर की कार्रवाई में आदेश है।

$ echo -e " \t   blahblah  \t  " | sed 's/^[ \t]*//;s/[ \t]*$//'
blahblah

आप यह hexdumpपुष्टि करने के लिए उपयोग कर सकते हैं कि sedकमांड वांछित वर्णों को सही ढंग से अलग कर रहा है।

$ echo -e " \t   blahblah  \t  " | sed 's/^[ \t]*//;s/[ \t]*$//' | hexdump -C
00000000  62 6c 61 68 62 6c 61 68  0a                       |blahblah.|
00000009

चरित्र वर्ग

आप वर्ण वर्ग के नामों का उपयोग शाब्दिक रूप से इस तरह सेट को सूचीबद्ध करने के बजाय कर सकते हैं [ \t]:

$ sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//' < file

उदाहरण

$ echo -e " \t   blahblah  \t  " | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'

अधिकांश GNU उपकरण जो नियमित अभिव्यक्ति (रेगेक्स) का उपयोग करते हैं, इन वर्गों का समर्थन करते हैं।

 [[:alnum:]]  - [A-Za-z0-9]     Alphanumeric characters
 [[:alpha:]]  - [A-Za-z]        Alphabetic characters
 [[:blank:]]  - [ \x09]         Space or tab characters only
 [[:cntrl:]]  - [\x00-\x19\x7F] Control characters
 [[:digit:]]  - [0-9]           Numeric characters
 [[:graph:]]  - [!-~]           Printable and visible characters
 [[:lower:]]  - [a-z]           Lower-case alphabetic characters
 [[:print:]]  - [ -~]           Printable (non-Control) characters
 [[:punct:]]  - [!-/:-@[-`{-~]  Punctuation characters
 [[:space:]]  - [ \t\v\f]       All whitespace chars
 [[:upper:]]  - [A-Z]           Upper-case alphabetic characters
 [[:xdigit:]] - [0-9a-fA-F]     Hexadecimal digit characters

शाब्दिक सेटों के बजाय इनका उपयोग करना हमेशा अंतरिक्ष की बर्बादी की तरह लगता है, लेकिन यदि आप अपने कोड के पोर्टेबल होने, या वैकल्पिक वर्ण सेटों (अंतरराष्ट्रीय सोचें) से निपटने के लिए चिंतित हैं, तो आप संभवतः कक्षा के नामों का उपयोग करना चाहेंगे। बजाय।

संदर्भ


ध्यान दें कि सामान्य मामले (यूनिकोड, आदि) के [[:space:]]बराबर नहीं है [ \t][[:space:]]शायद बहुत धीमी हो जाएगी (क्योंकि यूनिकोड में व्हॉट्सएप के कई और प्रकार हैं बस ' 'और '\t')। अन्य सभी के लिए समान।
ओलिवियर दुलाक

sed 's/^[ \t]*//'पोर्टेबल नहीं है। सामान्य रूप से POSIX को अंतरिक्ष, बैकलैश या tवर्णों के अनुक्रम को हटाने के लिए भी आवश्यकता होती है , और sedऐसा तब होता है जब POSIXLY_CORRECTपर्यावरण में GNU भी करता है।
स्टीफन चेजेलस 14

क्या होगा अगर मैं newlines वर्णों को ट्रिम करना चाहता हूं? '\ n \ n पाठ \ n \ n'
यूजीन बिरयुकोव

मुझे सेड सॉल्यूशन पसंद है क्योंकि अन्य साइड-इफेक्ट्स की कमी की वजह से ऑक सॉल्यूशन में कमी आती है। पहली भिन्नता तब काम नहीं करती है जब मैंने इसे OSX jsut पर अब bash में आज़माया था, लेकिन चरित्र वर्ग संस्करण काम करता है:sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
टोनी

@EugeneBiryukov मूल पोस्ट पर मेरी टिप्पणी देखें
टोनी

23

जैसा कि स्टीफन चेजेलस द्वारा स्वीकार किए गए उत्तर में सुझाया गया है , अब आप
एक स्क्रिप्ट बना सकते हैं /usr/local/bin/trim:

#!/bin/bash
awk '{$1=$1};1'

और उस फ़ाइल को निष्पादन योग्य अधिकार दें:

chmod +x /usr/local/bin/trim

अब आप trimउदाहरण के लिए हर आउटपुट पास कर सकते हैं :

cat file | trim

(नीचे दी गई टिप्पणियों के लिए: मैंने पहले while read i; do echo "$i"; done
भी इसका उपयोग किया था: जो ठीक भी काम करता है, लेकिन कम प्रदर्शन करने वाला है)


1
सौभाग्य अगर आपकी फ़ाइल बहुत बड़ी है और / या बैकस्लैश शामिल हैं।
don_crissti

1
@don_crissti: क्या आप कुछ और टिप्पणी कर सकते हैं ?, जो समाधान बड़ी फ़ाइलों के लिए बेहतर फिटिंग होगा, और यदि फ़ाइल बैकस्लैश में है तो मैं अपने समाधान को कैसे संशोधित कर सकता हूं?
रबॉ .77

3
आप का उपयोग करना होगा while read -r lineबैकस्लैश और संरक्षित करने के लिए ... फिर भी । बड़ी फ़ाइलों / गति के रूप में, वास्तव में, आपने सबसे खराब समाधान उठाया। मुझे नहीं लगता कि वहां कुछ भी बदतर है। पाठ खराब अभ्यास को संसाधित करने के लिए शेल लूप का उपयोग करने पर उत्तर क्यों देखें ? अंतिम उत्तर पर मेरी टिप्पणी सहित जहां मैंने एक गति बेंचमार्क के लिए एक लिंक जोड़ा। यहाँ के sedजवाब पूरी तरह से ठीक IMO हैं और इससे कहीं बेहतर हैं read
डॉन_क्रांति

@don_crissti ... और / या लाइनों के साथ शुरू हो रहा है -और 1 या अधिक ई, ई या n वर्णों के संयोजन के साथ , और / या NUL वर्ण हैं। इसके अलावा, अंतिम न्यूलाइन के बाद एक गैर-समाप्त लाइन को छोड़ दिया जाएगा।
स्टीफन चेज़लस

1
तुम भी (या अपने ~ / .bashrc या ~ / .zshrc आदि ...) / etc / प्रोफ़ाइल में एक उपनाम जोड़ सकते हैं उर्फ ट्रिम = "awk '{\ $ 1 = \ $ 1}; 1'"
जेफ क्लेटन

22

बिना तर्क के xargs ऐसा करते हैं।

उदाहरण:

trimmed_string=$(echo "no_trimmed_string" | xargs) 

1
यह एक पंक्ति के भीतर कई रिक्त स्थान भी अनुबंधित करता है, जो प्रश्न में अनुरोध नहीं किया गया था
रोमा

1
@roaima - सच है, लेकिन स्वीकृत उत्तर भी रिक्त स्थान को निचोड़ता है (जो प्रश्न में अनुरोध नहीं किया गया था)। मुझे लगता है कि यहां वास्तविक समस्या यह है कि xargsयदि इनपुट में बैकस्लैश और सिंगल कोट्स हैं, तो डिलीवर करने में विफल रहेंगे।
don_crissti

@don_crissti का मतलब यह नहीं है कि स्वीकृत उत्तर सही तरीके से पूछे गए प्रश्न का उत्तर देता है, हालाँकि। लेकिन इस मामले में यहाँ इसे एक चेतावनी के रूप में नहीं दिखाया गया जबकि स्वीकृत उत्तर में यह था। मुझे उम्मीद है कि भविष्य के पाठक की प्रासंगिकता के मामले में इस तथ्य को उजागर किया जाएगा।
रोज़ा

यह सिंगल कोट्स, डबल कोट्स, बैकस्लैश कैरेक्टर पर भी टूटता है। यह एक या अधिक echoइनवोकेशन भी चलाता है । कुछ इको कार्यान्वयन विकल्प और / या बैकस्लैश की प्रक्रिया भी करेंगे ... यह भी केवल सिंगल-लाइन इनपुट के लिए काम करता है।
स्टीफन चेज़लस

17
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'

यदि आप एक शेल चर में एक पंक्ति पढ़ रहे हैं, readतो पहले से ही जब तक अन्यथा निर्देश न दिया जाए


1
के लिए +1 read। इसलिए यदि आप पढ़ते समय पाइप करते हैं तो यह काम करता है:cat file | while read i; do echo $i; done
rubo77

1
@rubo को छोड़कर आपके उदाहरण में unquoted वैरिएबल भी शेल द्वारा रिप्रोड्यूस किया गया है। का echo "$i"सही प्रभाव देखने के लिए उपयोग करेंread
roaima

13

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

एक स्ट्रिंग से प्रमुख व्हाट्सएप को हटा दें:

shopt -s extglob
echo ${text##+([[:space:]])}

एक स्ट्रिंग से ट्रेलिंग व्हाट्सएप को हटा दें:

shopt -s extglob
echo ${text%%+([[:space:]])}

एक स्ट्रिंग से सभी व्हाट्सएप को हटा दें:

echo ${text//[[:space:]]}

एक स्ट्रिंग से सभी श्वेत-स्थान को हटाना दोनों अग्रणी और अनुगामी रिक्त स्थान (जैसे प्रश्न में) को हटाने के समान नहीं है।
कैटपोनोसिस

सबसे अच्छा समाधान - इसके लिए केवल बैश बिल्डिंस की आवश्यकता होती है और कोई बाहरी प्रक्रिया कांटे की आवश्यकता नहीं होती है।
पीटर

2
अच्छा लगा। यदि वे बाहरी कार्यक्रमों (जैसे कि awk या sed) में खींचने की ज़रूरत नहीं है, तो लिपियों को बहुत तेज़ी से चलाते हैं। यह ksh के "आधुनिक" (93u +) संस्करणों के साथ भी काम करता है।
user1683793

9

किसी दिए गए लाइन से सभी प्रमुख और अनुगामी रिक्त स्थान को हटाने के लिए एक 'पाइप्ड' टूल के लिए धन्यवाद, मैं 3 अलग-अलग तरीकों की पहचान कर सकता हूं जो पूरी तरह से बराबर नहीं हैं। ये अंतर इनपुट लाइन के शब्दों के बीच रिक्त स्थान की चिंता करते हैं। अपेक्षित व्यवहार के आधार पर, आप अपनी पसंद बना लेंगे।

उदाहरण

अंतर समझाने के लिए, इस डमी इनपुट लाइन पर विचार करें:

"   \t  A   \tB\tC   \t  "

टीआर

$ echo -e "   \t  A   \tB\tC   \t  " | tr -d "[:blank:]"
ABC

trवास्तव में एक साधारण आदेश है। इस स्थिति में, यह किसी भी स्थान या सारणीकरण वर्ण को हटा देता है।

awk

$ echo -e "   \t  A   \tB\tC   \t  " | awk '{$1=$1};1'
A B C

awk प्रमुख और टेलिंग स्पेस को हटाता है और शब्दों के बीच हर स्पेस को सिंगल स्पेस को निचोड़ता है।

एसईडी

$ echo -e "   \t  A   \tB\tC   \t  " | sed 's/^[ \t]*//;s/[ \t]*$//'
A       B   C

इस स्थिति में, sedशब्दों के बीच किसी भी स्थान को स्पर्श किए बिना अग्रणी और पूंछ वाले रिक्त स्थान को हटाता है।

टिप्पणी:

प्रति पंक्ति एक शब्द के मामले में, trकाम करता है।


इस ट्रिम को आगे
बढ़ाने में

उनके (कभी-कभी अप्रत्याशित) आउटपुट के साथ समाधानों की सूची के लिए +1।
टोनी

@ user61382 यह देर हो चुकी है, लेकिन मूल पोस्ट पर मेरी टिप्पणी देखें।
टोनी

@highmainurance: [:space:]कमांड के लिए, [: blank:] के बजाय tr, जैसे: ... | tr -d [:space:]newlines को भी हटाने के लिए उपयोग करें। (देखें: man tr)
tron5

6

sed उसके लिए एक महान उपकरण है:

                        # substitute ("s/")
sed 's/^[[:blank:]]*//; # parts of lines that start ("^")  with a space/tab 
     s/[[:blank:]]*$//' # or end ("$") with a space/tab
                        # with nothing (/)

आप इसका उपयोग अपने मामले के लिए या तो पाठ में पाइपिंग के लिए कर सकते हैं, उदा

<file sed -e 's/^[[...

या 'इनलाइन' पर अभिनय करके अगर आपका sedGNU एक है:

sed -i 's/...' file

लेकिन स्रोत को इस तरह से बदलना "खतरनाक" है क्योंकि यह अपरिवर्तनीय हो सकता है जब यह सही काम नहीं करता है (या तब भी जब यह करता है!), इसलिए पहले बैकअप (या उपयोग करें -i.bakजिसमें कुछ बीएसडी के लिए पोर्टेबल होने का लाभ है sed) !


2

अनुवाद कमांड काम करेगा

cat file | tr -d [:blank:]

4
यह कमांड सही नहीं है क्योंकि यह फाइल से सभी स्पेस को हटाता है , न कि केवल व्हाट्सएप को लीड करता है।
बजे ब्रायन रेडबर्ड

@BrianRedbeard आप सही हैं। यह अभी भी रिक्त स्थान के बिना, एक अखंड स्ट्रिंग के लिए एक उपयोगी उत्तर है।
एंथनी रटलेज

0

यदि स्ट्रिंग को ट्रिम करने की कोशिश की जा रही है, तो यह छोटा और निरंतर / सन्निहित है, कोई इसे बस किसी भी bash फ़ंक्शन के पैरामीटर के रूप में पास कर सकता है:

    trim(){
        echo $@
    }

    a="     some random string   "

    echo ">>`trim $a`<<"
Output
>>some random string<<
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.