আমি কিভাবে একটি নতুন লাইন প্রতিস্থাপন করতে পারি(\ n) sed ব্যবহার করে?




(20)

আমি কীভাবে নতুন কমান্ডটি প্রতিস্থাপন করতে পারি ( \n ) sed কমান্ড ব্যবহার করে?

আমি ব্যর্থ চেষ্টা করেছি:

sed 's#\n# #g' file
sed 's#^$# #g' file

আমি কিভাবে এটা ঠিক করব?


সহজ থেকে বুঝতে সমাধান

আমি এই সমস্যা ছিল। Kicker ছিল যে আমি BSD এর (ম্যাক ওএস এক্স) এবং GNU এর (লিনাক্স এবং Cygwin ) sed এবং tr তে কাজ করার সমাধান প্রয়োজন:

$ echo 'foo
bar
baz


foo2
bar2
baz2' \
| tr '\n' '\000' \
| sed 's:\x00\x00.*:\n:g' \
| tr '\000' '\n'

আউটপুট:

foo
bar
baz

(নতুন লাইন পিছনে আছে)

এটি লিনাক্স, ওএস এক্স, এবং বিএসডি -তে এমনকি UTF-8 সমর্থন ছাড়াই কাজ করে বা ক্র্যাফপি টার্মিনালের সাথে কাজ করে।

  1. অন্য অক্ষর দিয়ে নতুন লাইন স্যুইচ করার জন্য tr ব্যবহার করুন।

    NULL ( \000 বা \x00 ) চমৎকার কারণ \x00 UTF-8 সমর্থনের প্রয়োজন নেই এবং এটি ব্যবহার করা যাবে না।

  2. NULL মিলিত করার জন্য sed ব্যবহার করুন

  3. যদি আপনার প্রয়োজন হয় তবে অতিরিক্ত নতুন লাইনগুলি tr করতে tr ব্যবহার করুন


কোন স্ট্রিং সঙ্গে নতুন লাইন প্রতিস্থাপন, এবং শেষ সর্বশেষ লাইন প্রতিস্থাপন

বিশুদ্ধ tr সমাধান শুধুমাত্র একটি অক্ষর দিয়ে প্রতিস্থাপন করতে পারে, এবং বিশুদ্ধ sed সমাধানগুলি ইনপুটটির সর্বশেষ নতুন লাইনটিকে প্রতিস্থাপন করে না। নিচের সমাধানগুলি এই সমস্যার সমাধান করে এবং বাইনারি ডেটা (এমনকি একটি UTF-8 লোকেল সহও) নিরাপদ বলে মনে হয়:

printf '1\n2\n3\n' |
  sed 's/%/%p/g;s/@/%a/g' | tr '\n' @ | sed 's/@/<br>/g;s/%a/@/g;s/%p/%/g'

ফলাফল:

1<br>2<br>3<br>

Awk ব্যবহার করে:

awk "BEGIN { o=\"\" }  { o=o \" \" \$0 }  END { print o; }"

gnu sed একটি বিকল্প -z নল পৃথক রেকর্ড (লাইন) জন্য আছে। আপনি শুধু কল করতে পারেন:

sed -z 's/\n/ /g'

আপনি xargs ব্যবহার করতে পারেন - এটি ডিফল্টভাবে একটি স্থান দিয়ে \n প্রতিস্থাপন করবে।

যাইহোক, আপনার ইনপুটটি যদি বিচ্ছিন্ন unterminated quote কোনও ক্ষেত্রে থাকে তবে এটি সমস্যা হবে, উদাহরণস্বরূপ যদি প্রদত্ত লাইনের উদ্ধৃতি লক্ষণ মেলে না।


আমি একজন বিশেষজ্ঞ নই, তবে আমি মনে করি আপনি প্রথমে প্যাটার্ন স্পেসে পরবর্তী লাইন যুক্ত করতে হবে, বিজ " N " ব্যবহার করে। সেড অ্যান্ড অ্যাজক (ডেল ডঘের্টি এবং আর্নল্ড রবিনস; ওরেলি 1997 , পূর্বরূপে পৃষ্ঠা 107) বইটির "অ্যাডভান্সড সিড কমান্ড" বিভাগে "মাল্টিলাইন প্যাটার্ন স্পেস" থেকে:

মাল্টিলাইন পরবর্তী (এন) কমান্ড ইনপুট একটি নতুন লাইন পড়া এবং প্যাটার্ন স্পেস বিষয়বস্তুর মধ্যে যোগ করে একটি multiline প্যাটার্ন স্থান তৈরি করে। প্যাটার্ন স্পেস এবং নতুন ইনপুট লাইনের আসল সামগ্রীগুলি একটি নতুন লাইন দ্বারা পৃথক করা হয়। এমবেডেড নতুন লাইনের অক্ষরটি পাল্টা ক্রম অনুসারে "\ n" প্যাটার্নগুলির সাথে মিলে যেতে পারে। একটি মাল্টিলাইন প্যাটার্ন স্পেসে, মেটাচারার "^" প্যাটার্ন স্পেসের প্রথম চরিত্রের সাথে মেলে এবং চরিত্রগুলি কোনও এমবেডেড নতুন লাইন অনুসরণ করে না। একইভাবে, "$" শুধুমাত্র প্যাটার্ন স্পেসে চূড়ান্ত নতুন লাইনের সাথে মেলে, এবং কোনও এমবেডেড নয়লাইন (গুলি) নয়। পরবর্তী কমান্ডটি কার্যকর হওয়ার পরে, স্ক্রিপ্টের পরে পরবর্তী কমান্ডগুলিতে নিয়ন্ত্রণ করা হয়।

man sed থেকে:

[2addr] এন

আসল উপাদান থেকে সংযুক্ত উপাদান আলাদা করার জন্য একটি এমবেডেড নতুন লাইন চরিত্র ব্যবহার করে প্যাটার্ন স্পেসে ইনপুটটির পরবর্তী লাইন যুক্ত করুন। উল্লেখ্য যে বর্তমান লাইন নম্বর পরিবর্তন।

আমি এটি ব্যবহার করেছি (একাধিক) খারাপভাবে বিন্যাসযুক্ত লগ ফাইল, যা অনুসন্ধান স্ট্রিং একটি "অনাথ" পরবর্তী লাইনে পাওয়া যেতে পারে।


উপরের "ট্র" সমাধানটির প্রতিক্রিয়ায়, উইন্ডোজ (সম্ভবত ট্রু এর Gnuwin32 সংস্করণ ব্যবহার করে) প্রস্তাবিত সমাধান:

tr '\n' ' ' < input

আমার জন্য কাজ করছিল না, এটি কোনও কারণে ত্রুটি বা আসলে \ nw / '' প্রতিস্থাপন করবে।

Tr এর অন্য বৈশিষ্ট্য ব্যবহার করে, "মুছে ফেলুন" বিকল্পটি -ড কাজ করেছে যদিও:

tr -d '\n' < input

বা '\ r \ n' এর পরিবর্তে '\ n'


একটি সংক্ষিপ্ত অদ্ভুত বিকল্প:

awk 1 ORS=' '

ব্যাখ্যা

একটি awk প্রোগ্রাম শর্তাবলী নির্মিত হয় যা শর্তাধীন কোড-ব্লক গঠিত, অর্থাত্:

condition { code-block }

কোড-ব্লক বাদ দেওয়া হলে, ডিফল্ট ব্যবহার করা হয়: { print $0 } । সুতরাং, 1 সত্য শর্ত হিসাবে ব্যাখ্যা করা হয় এবং প্রতিটি লাইনের জন্য print $0 করা হয়।

যখন awk ইনপুটটি পড়ে তখন এটি RS (রেকর্ড বিভাজক) এর মানের ভিত্তিতে রেকর্ডে বিভক্ত হয়, যা ডিফল্টভাবে একটি নতুন লাইন হয়, সুতরাং ডিফল্টভাবে ডিফল্টভাবে ইনপুট লাইন অনুসারে পজিশন করে। বিভাজন এছাড়াও ইনপুট রেকর্ড থেকে RS stripping জড়িত থাকে।

এখন, যখন একটি রেকর্ড মুদ্রণ করা হয়, ORS (আউটপুট রেকর্ড বিভাজক) এটি যুক্ত করা হয়, ডিফল্ট আবার একটি নতুন লাইন। সুতরাং একটি স্থান থেকে ORS পরিবর্তন করে সব নতুন লাইন স্পেস পরিবর্তন করা হয়।


এটি সাধারণ যে "স্বাভাবিক" প্রতিস্থাপনের পরে নতুন লাইন প্রবর্তন করে। প্রথম, এটি নতুন লাইন গৃহস্থালি trims, তারপর এটি আপনার নির্দেশাবলী অনুযায়ী প্রসেস, তারপর এটি একটি নতুন লাইন প্রবর্তন।

সিডি ব্যবহার করে আপনি প্রতিটি ইনপুট লাইনের জন্য আপনার পছন্দের স্ট্রিং সহ একটি লাইন (নতুন লাইন গৃহস্থালি নয়) এর "শেষ" প্রতিস্থাপন করতে পারেন; কিন্তু, sed বিভিন্ন লাইন আউটপুট হবে। উদাহরণস্বরূপ, ধরুন আপনি "===" দিয়ে "লাইনের শেষ" প্রতিস্থাপন করতে চান (একটি স্থান সহ প্রতিস্থাপন করার চেয়ে আরো সাধারণ):

PROMPT~$ cat <<EOF |sed 's/$/===/g'
first line
second line
3rd line
EOF

first line===
second line===
3rd line===
PROMPT~$

নতুন লাইন গৃহস্থালিটি স্ট্রিং দিয়ে প্রতিস্থাপন করার জন্য, আপনি অদক্ষভাবে, যদিও, "নির্দিষ্ট গৃহস্থালি" দিয়ে নতুন লাইনের প্রতিস্থাপন করার আগে, পূর্বে নির্দেশিত tr হিসাবে ব্যবহার করতে পারেন এবং তারপরে যে বিশেষ স্ট্রিংটি আপনি চান তা দিয়ে প্রতিস্থাপন করতে sed ব্যবহার করুন। ।

উদাহরণ স্বরূপ:

PROMPT~$ cat <<EOF | tr '\n' $'\x01'|sed -e 's/\x01/===/g'
first line
second line
3rd line
EOF

first line===second line===3rd line===PROMPT~$

এর উত্তরঃ একটি লেবেল ...

আমি কিভাবে একটি নতুন লাইন প্রতিস্থাপন করতে পারি (\ n) sed ব্যবহার করে?

... কমান্ড লাইনে ফ্রিবসড 7.2 এ কাজ করে না:

( echo foo ; echo bar ) | sed ':a;N;$!ba;s/\n/ /g'
sed: 1: ":a;N;$!ba;s/\n/ /g": unused label 'a;N;$!ba;s/\n/ /g'
foo
bar

কিন্তু যদি আপনি একটি স্ক্রিপ্টে sed ​​স্ক্রিপ্টটি ব্যবহার করেন বা ব্যবহার করেন -ইড স্ক্রিপ্টটি "বিল্ড" করতে ...

> (echo foo; echo bar) | sed -e :a -e N -e '$!ba' -e 's/\n/ /g'
foo bar

অথবা ...

> cat > x.sed << eof
:a
N
$!ba
s/\n/ /g
eof

> (echo foo; echo bar) | sed -f x.sed
foo bar

হয়তো ওএস এক্স মধ্যে sed ​​অনুরূপ।


কে কে দরকার? এখানে bash উপায়:

cat test.txt |  while read line; do echo -n "$line "; done

জিএনইউ সঙ্গে এই সমাধান ব্যবহার করুন sed :

sed ':a;N;$!ba;s/\n/ /g' file

এটি একটি লুপে পুরো ফাইলটি পড়বে, তারপরে একটি স্থান সহ নতুন লাইন প্রতিস্থাপন করবে।

ব্যাখ্যা:

  1. মাধ্যমে একটি লেবেল তৈরি করুন :a
  2. N মাধ্যমে প্যাটার্ন স্থান বর্তমান এবং পরবর্তী লাইন যোগ করুন।
  3. যদি আমরা শেষ লাইনের আগে, তৈরি লেবেলটির শাখা $!ba ( $! মানে শেষ লাইনে এটি করা হবে না কারণ এটি একটি চূড়ান্ত নতুন লাইন হওয়া উচিত)।
  4. অবশেষে প্রতিস্থাপন প্রতি নতুন রেখাটিকে প্যাটার্ন স্পেসে (যা পুরো ফাইলটি) একটি স্থান দিয়ে প্রতিস্থাপন করে।

এখানে ক্রস-প্ল্যাটফর্ম সামঞ্জস্যপূর্ণ সিনট্যাক্স রয়েছে যা বিএসডি এবং ওএস এক্স এর সিডি ( @ বেঞ্জি মন্তব্য অনুসারে ) দিয়ে কাজ করে:

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file

আপনি দেখতে পারেন, এই অন্যথায় সহজ সমস্যা জন্য sed ব্যবহার করে সমস্যাযুক্ত। একটি সহজ এবং পর্যাপ্ত সমাধান জন্য এই উত্তর দেখুন ।


পরিবর্তে tr ব্যবহার করবেন?

tr '\n' ' ' < input_filename

অথবা সম্পূর্ণরূপে নতুন অক্ষর মুছে ফেলুন:

tr -d '\n' < input.txt > output.txt

অথবা যদি আপনার GNU সংস্করণ থাকে (তার দীর্ঘ বিকল্পগুলির সাথে)

tr --delete '\n' < input.txt > output.txt

ফাঁকা লাইন মুছে ফেলার জন্য:

sed -n "s/^$//;t;p;"

ম্যাক ওএস এক্স (ফ্রিবিএসডি সিডি ব্যবহার করে):

# replace each newline with a space
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta'
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta

Perl সংস্করণ আপনি প্রত্যাশিত উপায় কাজ করে।

perl -i -p -e 's/\n//' file

মতামত হিসাবে নির্দিষ্ট, এটা উল্লেখযোগ্য যে এই সম্পাদনা জায়গায়। -i.bak আপনার নিয়মিত অভিব্যক্তিটি যতটা স্মার্ট হিসাবে বিবেচিত না হবার ক্ষেত্রে প্রতিস্থাপনের আগে মূল ফাইলের ব্যাকআপ দেয়।


@OP, যদি আপনি একটি ফাইলের নতুন লাইন প্রতিস্থাপন করতে চান তবে আপনি কেবলমাত্র dos2unix (অথবা unix2dox) ব্যবহার করতে পারেন

dos2unix yourfile yourfile

আপনি এই পদ্ধতি ব্যবহার করতে পারেন

sed 'x;G;1!h;s/\n/ /g;$!d'

ব্যাখ্যা

x   - which is used to exchange the data from both space (pattern and hold).
G   - which is used to append the data from hold space to pattern space.
h   - which is used to copy the pattern space to hold space.
1!h - During first line won't copy pattern space to hold space due to \n is
      available in pattern space.
$!d - Clear the pattern space every time before getting next line until the
      last line.

প্রবাহ:
যখন প্রথম লাইনটি ইনপুট থেকে আসে, এক্সচেঞ্জ তৈরি হয়, তাই 1 স্থান ধরে রাখে এবং \ n প্যাটার্ন স্পেসে আসে, তারপর হোল্ড স্পেসটি প্যাটার্ন স্পেসে যোগ করে এবং তারপরে প্রতিস্থাপন সঞ্চালিত হয় এবং প্যাটার্ন স্পেস মুছে ফেলে।
দ্বিতীয় লাইন বিনিময় সময়, 2 স্থান ধরে রাখা হয় এবং 1 প্যাটার্ন স্পেসে আসে, তারপর প্যাটার্ন স্পেসে Gহোল্ড স্পেস যুক্ত করুন, তারপরে hপ্যাটার্নটি অনুলিপি করুন এবং প্রতিস্থাপন তৈরি এবং মুছে ফেলা হয়। Eof পৌঁছে পর্যন্ত এই অপারেশন অব্যাহত তারপর সঠিক ফলাফল মুদ্রণ।


আমি এই উত্তরটি পোস্ট করেছি কারণ আমি sedউপরে প্রদত্ত প্রশংসনীয় উদাহরণ দিয়ে চেষ্টা করেছি যা আমার ইউনিক্স বক্সে আমার জন্য কাজ করে না এবং আমাকে ত্রুটি বার্তা দেয় Label too long: {:q;N;s/\n/ /g;tq}। অবশেষে আমি আমার প্রয়োজনীয়তা তৈরি করেছি এবং তাই এখানে সমস্ত ইউনিক্স / লিনাক্স পরিবেশে কাজ করে যাচ্ছি: -

line=$(while read line; do echo -n "$line "; done < yoursourcefile.txt)
echo $line |sed 's/ //g' > sortedoutput.txt

প্রথম লাইন ফাইল থেকে সমস্ত নতুন লাইন মুছে ফেলা হবে yoursourcefile.txtএবং একটি একক লাইন উত্পাদন করবে। এবং দ্বিতীয় sedকমান্ড এটি থেকে সব স্পেস মুছে ফেলা হবে।


sed '1h;1!H;$!d
     x;s/\n/ /g' YourFile

এটি বিশাল ফাইলগুলির (বাফার সীমা) জন্য কাজ করে না, তবে ফাইলটি ধরে রাখতে যথেষ্ট মেমরি থাকলে এটি খুব কার্যকর। (সংশোধন H-> 1h;1!H@ হিলোজ্যাকের ভাল মন্তব্যের পরে)

পড়ার সময় নতুন লাইন পরিবর্তন করার আরেকটি সংস্করণ (আরো cpu, কম মেমরি)

 sed ':loop
 $! N
 s/\n/ /
 t loop' YourFile