सार
नई लाइन के बिना प्रिंट लाइनें, केवल एक नई लाइन जोड़ें अगर प्रिंट करने के लिए एक और रेखा है।
$ printf 'one\ntwo\n' |
awk '{ printf( "%s%s" , NR>1?"\n":"" , $0 ) }'; echo " done"
one
two done
अन्य उपाय
यदि हम एक फ़ाइल के साथ काम कर रहे थे, तो हम केवल एक चरित्र को उससे अलग कर सकते हैं (यदि यह एक नई पंक्ति में समाप्त होता है):
removeTrailNewline () {[$ (टेल -c 1 "$ 1")]] || truncate -s-1 "$ 1"; }
यह एक तेज़ समाधान है क्योंकि इसे फ़ाइल से केवल एक वर्ण को पढ़ने की आवश्यकता है और फिर इसे truncate
पूरी फ़ाइल को पढ़े बिना सीधे ( ) में हटा दें ।
हालांकि, स्टडिन (एक धारा) के डेटा के साथ काम करते समय डेटा को पढ़ा जाना चाहिए, यह सब। और, यह पढ़ते ही "भस्म" हो जाता है। कोई पीछे नहीं (ट्रंकट के साथ)। एक धारा के अंत का पता लगाने के लिए हमें धारा के अंत तक पढ़ना होगा। उस बिंदु पर, इनपुट स्ट्रीम पर वापस जाने का कोई तरीका नहीं है, डेटा पहले ही "भस्म" हो चुका है। इसका मतलब है कि डेटा को बफर के कुछ रूप में संग्रहीत किया जाना चाहिए जब तक कि हम स्ट्रीम के अंत से मेल नहीं खाते हैं और फिर बफर में डेटा के साथ कुछ करते हैं।
समाधानों में सबसे स्पष्ट है कि स्ट्रीम को फाइल में बदलना और उस फाइल को प्रोसेस करना। लेकिन सवाल धारा के कुछ प्रकार के फिल्टर के लिए पूछता है। अतिरिक्त फ़ाइलों के उपयोग के बारे में नहीं।
परिवर्तनशील
भोले समाधान एक चर में पूरे इनपुट पर कब्जा करने के लिए किया जाएगा:
FilterOne(){ filecontents=$(cat; echo "x"); # capture the whole input
filecontents=${filecontents%x}; # Remove the "x" added above.
nl=$'\n'; # use a variable for newline.
printf '%s' "${filecontents%"$nl"}"; # Remove newline (if it exists).
}
printf 'one\ntwo' | FilterOne ; echo 1done
printf 'one\ntwo\n' | FilterOne ; echo 2done
printf 'one\ntwo\n\n' | FilterOne ; echo 3done
याद
मेमोरी में एक पूरी फाइल को सेड के साथ लोड करना संभव है। Sed में अंतिम पंक्ति पर अनुगामी newline से बचना असंभव है। GNU सेड एक अनुगामी न्यूलाइन को प्रिंट करने से बच सकता है, लेकिन केवल अगर स्रोत फ़ाइल पहले से ही गायब है। तो, नहीं, सरल sed मदद नहीं कर सकता।
-z
विकल्प के साथ GNU awk को छोड़कर :
sed -z 's/\(.*\)\n$/\1/'
Awk (किसी भी awk) के साथ, पूरी स्ट्रीम को खिसकाएं, और printf
यह अनुगामी न्यूलाइन के बिना।
awk ' { content = content $0 RS }
END { gsub( "\n$", "", content ); printf( "%s", content ) }
'
मेमोरी में एक पूरी फ़ाइल लोड करना एक अच्छा विचार नहीं हो सकता है, यह बहुत अधिक मेमोरी का उपभोग कर सकता है।
स्मृति में दो लाइनें
Awk में, हम पिछली लाइन को एक वेरिएबल में स्टोर करके और वर्तमान में प्रिन्ट करके दो लूप प्रति लूप प्रोसेस कर सकते हैं:
awk 'NR>1{print previous} {previous=$0} END {printf("%s",$0)}'
प्रत्यक्ष प्रसंस्करण
लेकिन हम बेहतर कर सकते थे।
अगर हम बिना लाइन के वर्तमान लाइन को प्रिंट करते हैं और अगली लाइन के मौजूद होने पर ही एक नई लाइन प्रिंट करते हैं, तो हम एक बार में एक लाइन को प्रोसेस करते हैं और आखिरी लाइन में एक ट्रेलिंग न्यूलाइन नहीं होगी :
awk 'NR == 1 {प्रिंटफ ("% s", $ 0); अगला}; {प्रिंटफ ("\ n% s", $ 0)} '
या, किसी और तरीके से लिखा गया है:
awk 'NR>1{ print "" }; { printf( "%s", $0 ) }'
या:
awk '{ printf( "%s%s" , NR>1?"\n":"" , $0 ) }'
इसलिए:
$ printf 'one\ntwo\n' | awk '{ printf( "%s%s" , NR>1?"\n":"" , $0 ) }'; echo " done"
one
two done
chomp
, क्योंकिchomp
केवल एक ही अनुगामी न्यूलाइन पर हटा दिया जाता है।