বিমূর্ত
নিউলাইন ছাড়াই লাইনগুলি মুদ্রণ করুন, মুদ্রণের জন্য অন্য লাইন থাকলে কেবল একটি নতুন লাইন যুক্ত করুন।
$ printf 'one\ntwo\n' |
awk '{ printf( "%s%s" , NR>1?"\n":"" , $0 ) }'; echo " done"
one
two done
অন্যান্য সমাধান
যদি আমরা কোনও ফাইল নিয়ে কাজ করি তবে আমরা কেবলমাত্র এটি থেকে একটি অক্ষর ছিন্ন করতে পারি (যদি এটি একটি নতুন লাইনে শেষ হয়):
মুছে ফেলা ট্রেলইনলাইন () {[[$ (লেজ -c 1 "$ 1")]] || কাটা কাটা -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
স্মৃতি
সেড দিয়ে মেমরিতে একটি সম্পূর্ণ ফাইল লোড করা সম্ভব। সিডে শেষ লাইনে ট্রেলিং করা নতুন লাইন এড়ানো অসম্ভব। জিএনইউ শেড একটি নতুন ট্র্যাকিং নতুন লাইনের মুদ্রণ এড়াতে পারে তবে কেবল যদি উত্স ফাইলটি এটি অনুপস্থিত থাকে। সুতরাং, না, সরল সেড সাহায্য করতে পারে না।
-z
বিকল্পটি সহ জিএনইউ অ্যাডকে বাদ দিয়ে :
sed -z 's/\(.*\)\n$/\1/'
Awk (যে কোনও awk) এর সাহায্যে পুরো স্ট্রিম স্লার্প করুন এবং printf
এটি নতুন লাইনের পিছনে ছাড়াই।
awk ' { content = content $0 RS }
END { gsub( "\n$", "", content ); printf( "%s", content ) }
'
পুরো ফাইলটিকে মেমোরিতে লোড করা ভাল ধারণা নাও হতে পারে, এটি প্রচুর স্মৃতিতে গ্রাস করতে পারে।
স্মৃতিতে দুটি লাইন
অজানাতে, আমরা ভেরিয়েবলের মধ্যে পূর্ববর্তী লাইনটি সঞ্চয় করে এবং বর্তমানের একটি মুদ্রণ করে লুপ প্রতি দুটি লাইন প্রক্রিয়া করতে পারি:
awk 'NR>1{print previous} {previous=$0} END {printf("%s",$0)}'
সরাসরি প্রক্রিয়াজাতকরণ
তবে আমরা আরও ভাল করতে পারে।
আমরা যদি নতুন লাইনটি ছাড়াই বর্তমান লাইনটি মুদ্রণ করি এবং পরবর্তী লাইনের উপস্থিতি কেবল তখনই একটি নতুন লাইন প্রিন্ট করি, আমরা একবারে একটি লাইন প্রসেস করি এবং শেষ লাইনে শেষের লাইনটি থাকবে না :
awk 'NR == 1 {printf ("% s", $ 0); পরের next; {প্রিন্টফ ("\ 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
কেবলমাত্র একটির পিছনে থাকা নতুন লাইনটি মুছে ফেলা হয়।