লাইনটি কীভাবে মুছে ফেলা যায় যদি এতে একবারে কোনও অক্ষর থাকে


10

আমি কোনও ফাইল থেকে একটি লাইন সরাতে চাই যেখানে কেবলমাত্র একবারে একটি নির্দিষ্ট অক্ষর থাকে, যদি এটি একাধিকবার উপস্থিত হয় বা উপস্থিত না থাকে তবে লাইনটি ফাইলটিতে রাখুন।

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

DTHGTY
FGTHDC
HYTRHD
HTCCYD
JUTDYC

এখানে, আমি যে চরিত্রটি মুছতে চাইছি তা হ'ল C, কমান্ডটি লাইনগুলি সরিয়ে ফেলবে FGTHDCএবং JUTDYCকারণ সেগুলি Cঠিক একবারে রয়েছে।

আমি sedবা এটি ব্যবহার করে কীভাবে এটি করতে পারি awk?

উত্তর:


20

ইন awkআপনি কিছু ক্ষেত্র বিভাজক সেট করতে পারেন। আপনি যদি এটি সেট করে রাখেন C, তারপরে আপনার যতগুলি ক্ষেত্র রয়েছে তার মতো +1 হবে C

সুতরাং আপনি যদি বলেন যে awk -F'C' '{print NF}' <<< "C1C2C3"আপনি পেয়েছেন 4: CCC3 টি Cএর মধ্যে রয়েছে এবং তাই 4 টি ক্ষেত্র।

আপনি যা অপসারণ লাইন করতে চান Cঠিক একবার ঘটে। এটি বিবেচনায় রেখে, আপনার ক্ষেত্রে আপনি সেই লাইনগুলি সরাতে চাইবেন যেখানে ঠিক দুটি Cক্ষেত্র রয়েছে। সুতরাং কেবল তাদের এড়িয়ে যান:

$ awk -F'C' 'NF!=2' file
DTHGTY
HYTRHD
HTCCYD

4
awkফিল্ড বিভাজকের চটজলদি ব্যবহার !
ভ্যালেন্টাইন বি।

ডিফার্ট কেস (এফএস = "") এর মতো হস্তক্ষেপ করা, এটি শীর্ষস্থানগুলি ($ 1 = লাইনের প্রথম অ-স্থান) উপেক্ষা করে এবং পুনরাবৃত্তি (আপনার ক্ষেত্র 1 এবং ক্ষেত্র 2 পৃথক করার জন্য 5 স্পেস থাকতে পারে) ... স্থান সম্ভবত বিশেষভাবে চিকিত্সা করা হয়? (এটি দেখতে, কেউ awk 'BEGIN { print "FS={" FS"}","OFS={" OFS "}";} {printf "%d fields : ",NF; for (i=1;i<=NF;i++) {printf "{" $i "} ";}; print "" }'এটিকে কিছু লাইন খাওয়াতে এবং খাওয়াতে পারে, কিছুতে একাধিক স্প্যাস রয়েছে এবং অন্যরা স্থান (গুলি) দিয়ে শুরু করে)
অলিভিয়ার ডুলাক

2
@ অলিভিয়ারডুলাক, হ্যাঁ, পসিক্স দ্বারা নির্দিষ্ট হিসাবে স্থানটি বিশেষভাবে পরিচালনা করা হয় ।
ওয়াইল্ডকার্ড

8

সিড পদ্ধতির:

sed -i '/^[^C]*C[^C]*$/d' input

-i বিকল্পটি ইন-প্লেস ফাইল পরিবর্তনের অনুমতি দেয়

/^[^C]*C[^C]*$/- লাইনগুলির সাথে মেলে যা Cকেবল একবারে থাকে

d - মিলিত লাইনগুলি মুছুন


8

এটি এর সাথে করা যেতে পারে sed:

কোড:

sed '/C.*C/p;/C/d' file1

ফলাফল:

DTHGTY
HYTRHD
HTCCYD

কিভাবে?

  1. এর Cমাধ্যমে কমপক্ষে দুটি অনুলিপি সহ যে কোনও লাইন মেলে এবং মুদ্রণ করুন/C.*C/p
  2. এর Cমাধ্যমে যে কোনও লাইন মুছুন /C/d, এর মধ্যে ইতিমধ্যে পদক্ষেপ 1 এ মুদ্রিত লাইনগুলি অন্তর্ভুক্ত রয়েছে
  3. ডিফল্ট বাকি লাইন মুদ্রণ

2
চতুর বিকল্প পদ্ধতির; আমি এটা পছন্দ করি.
ওয়াইল্ডকার্ড

6

এটি সি এর ঠিক এক সংঘটন সহ লাইনগুলি সরিয়ে দেয়

grep -v '^[^C]*C[^C]*$' file

নিয়মিত প্রকাশটি এমন [^C]একটি চরিত্রের সাথে মেলে যা সি (বা নিউলাইন) নয় এবং পুনরাবৃত্তি অপারেটর (ওরফে ক্লিন তারকা) *পূর্ববর্তী অভিব্যক্তির শূন্য বা আরও পুনরাবৃত্তি নির্দিষ্ট করে।

grep(এবং বেশিরভাগ অন্যান্য পাঠ্য-ভিত্তিক সরঞ্জাম) থেকে ডিফল্ট আউটপুটটি স্ট্যান্ডার্ড আউটপুট হয়; একটি নতুন ফাইলে পুনর্নির্দেশ করুন এবং এটি যদি আপনি চান তবে সম্ভবত এটি মূল ফাইলের উপরে সরিয়ে দিন। sed -iইন-প্লেস এডিটিংয়ের জন্য একই রেজেক্স ব্যবহার করা যেতে পারে :

sed -i '/^[^C]*C[^C]*$/d' file

(কিছু প্ল্যাটফর্মে, উল্লেখযোগ্যভাবে * ম্যাকোস সহ বিএসডি, -iবিকল্পের জন্য একটি আর্গুমেন্ট দরকার, যেমন -i ''))


1
sed -i '/^[^C]*C[^C]*$/d' file- এমন শোনা যাচ্ছে যে এটি আগে পোস্ট করা হয়েছিল, আপনি কীভাবে ভাবেন, চুরি?
রোমানপেরেখারেস্ট

1
আসলে, কিছু নকল আছে। আমি grepউত্তর দিয়ে শুরু করেছি তবে এটি স্পষ্টতই sed -iবৈকল্পিক পর্যন্ত প্রসারিত । আপনার উত্তরটি দেখেনি কারণ আমি পূর্ববর্তী grepউত্তরগুলি সন্ধান করছিলাম ।
ট্রিপলি

1
এটা ঠিক স্পষ্টভাবে এড়াতে নিরাপদ -iসঙ্গে sedএর পরিবর্তে একটি নতুন ফাইলে পুনর্নির্দেশ এবং যদি যে মূল প্রতিস্থাপন sedইউটিলিটি কোন ত্রুটি সহ প্রস্থান করেছে।
কুসালানন্দ

2
বাgrep -vx '[^C]*C[^C]*'
স্টাফেন চেজেলাস

@ কুসালানন্দ তবে তারপরেও আপনি সম্ভবত grepএটি ব্যবহার করতে পারেন কারণ এটি পরিষ্কার এবং আরও শক্তিশালী (বিশেষত, sedকম তথ্যমূলক প্রস্থান কোড রয়েছে)।
ট্রিপলি

4

একটি ফাইলের স্ক্রিপ্টের সম্পাদনার জন্য POSIX সরঞ্জাম (বরং মান আউট রুপান্তরিত করা বিষয়বস্তু প্রিন্টিং বেশী) হল ex

printf '%s\n' 'g/^[^C]*C[^C]*$/d' x | ex file.txt

আপনার শেডের সংস্করণ যদি এটি সমর্থন করে তবে আপনি এটি ব্যবহারsed -i করতে পারেন, আপনি সচেতন হন যে এটি পোর্টেবল নয় যদি আপনি কোনও স্ক্রিপ্ট লিখে থাকেন যা বিভিন্ন ধরণের সিস্টেমে চালানোর উদ্দেশ্যে।


ডেভিড ফোস্টার মন্তব্য মন্তব্য জিজ্ঞাসা:

আপনি ব্যবহার করছেন printfএবং না করছেন এর echoমতো কোনও কারণ আছে কি ex -c COMMAND?

উত্তর: হ্যাঁ

জন্য printfবনাম echoএটা বহনযোগ্যতা একটি প্রশ্ন; দেখতে কেন প্রতিধ্বনি চেয়ে printf, উত্তম? এবং কমান্ডগুলি ব্যবহার করে নতুন লাইনগুলি ছেদ করা আরও সহজ printf

জন্য printf ... | exবনাম ex -c ..., এটা ত্রুটি পরিচালনা একটি প্রশ্ন। এই নির্দিষ্ট কমান্ডের জন্য এটি কোনও ব্যাপার নয়, তবে সাধারণভাবে এটি করে; উদাহরণস্বরূপ, রাখার চেষ্টা করুন

ex -c '%s/this pattern is not in the file/replacement text/g | x' filename

একটি স্ক্রিপ্টে। নিম্নলিখিতগুলির সাথে বিপরীতে:

printf '%s\n' '%s/no matching lines/replacement/g' x | ex file

প্রথমটি ঝুলবে এবং ইনপুটটির জন্য অপেক্ষা করবে; exকমান্ডটি ইওএফ প্রাপ্ত হলে দ্বিতীয়টি প্রস্থান করবে , সুতরাং স্ক্রিপ্টটি চালিয়ে যাবে। বিকল্প workarounds যেমন s///e, তবে তারা POSIX দ্বারা নির্দিষ্ট করা হয় না। আমি পোর্টেবল ফর্মটি ব্যবহার করতে পছন্দ করি যা উপরে দেখানো হয়েছে।

gকমান্ডের জন্য অবশ্যই শেষে একটি নতুন লাইন থাকা উচিত এবং আমি printfএকক উদ্ধৃতিতে একটি নতুন লাইন এম্বেড করার পরিবর্তে কমান্ডগুলি মোড়ানো ব্যবহার করতে পছন্দ করি ।


1
আপনি ব্যবহার করছেন printfএবং না করছেন এর echoমতো কোনও কারণ আছে কি ex -c COMMAND?
ডেভিড ফোস্টার

@ ডেভিডফোস্টার, হ্যাঁ আমি আপনাকে মন্তব্যে জবাব দিতে শুরু করেছি তবে এটি দীর্ঘ বেড়েছে, তাই আমি এটি উত্তরে যুক্ত করেছি।
ওয়াইল্ডকার্ড

ধন্যবাদ এবং +1! আমি printfবনাম সম্পর্কে জানতাম echo(যদিও আমি সাধারণত পছন্দ করি echoযখন যুক্তিটি হার্ড-কোডেড থাকে) তবে exএখন পর্যন্ত আমি ব্যাপকভাবে ব্যবহার করি নি ।
ডেভিড ফোস্টার 20

2

পার্ল ব্যবহার করে বেশ কয়েকটি বিকল্প রয়েছে।

যেহেতু আপনি কেবল একটি একটি চরিত্রের tr/C//সাথে মেলে, তাই এর মিলগুলির সংখ্যার ফিরিয়ে দিতে আপনি (কোনও প্রতিস্থাপন ছাড়াই অনুবাদ) ব্যবহার করতে পারেন C:

perl -lne 'print if tr/C// != 1' file

আরও সাধারণভাবে, আপনি যদি কোনও মাল্টি-ক্যারেক্টার স্ট্রিং বা নিয়মিত এক্সপ্রেশন মেলাতে চান তবে আপনি এটি ব্যবহার করতে পারেন:

perl -lne 'print if (@m = /C/g) != 1' file

এটি /C/gএকটি তালিকাতে নিয়মিত অভিব্যক্তির মিলগুলি নির্ধারণ করে @mএবং যখন তালিকার দৈর্ঘ্য না হয় তখন লাইনগুলি মুদ্রণ করে 1

-iসুইচ "ইন-জায়গা" সম্পাদনা যোগ করা যেতে পারে।


2
sed -e '
  s/C/&/2;t   # when 2nd C matches skip processing and print
  /C/d        # either one C or no C, so delete on C
'

sed -e '
   /C/!b     # no C, skip processing and print
   /C.*C/!d  # not(at least 2 C) => 1 C => delete
'

perl -lne 's/C/C/g == 1 or print'

নোট করুন যে এটি জিএনইউ ধরেছে sed, t #...সাধারণত #...বেশিরভাগ অন্যান্য sedবাস্তবায়নে ডাকা লেবেলে শাখা থাকে ।
স্টাফেন চেজেলাস

এমনকি !bজিএনইউ সেড যেহেতু শাখা লেবেল বা তার পরে একটি নতুন লাইন ছাড়া কিছুই পছন্দ করে না।

হ্যাঁ, b, t, :, }(এবং r file, w file...) তাদের পর কমান্ড একই লাইনে থাকতে পারে না। আপনি পৃথক -eবিকল্প ব্যবহার করতে পারেন ।
স্টাফেন চেজেলাস

আপনার পার্ল বিকল্পটি সঠিক আউটপুট উত্পাদন করে না। আমার ধারণা আপনি gমডিফায়ার যুক্ত করতে ভুলে গেছেন ।
টম ফেনেক

আপনি কি সঠিক আছেন আমি এটা ঠিক করছি। ধন্যবাদ।

1

যে কেউ awkবিশেষভাবে চান, আমি প্রস্তাব দিই

awk '/C[^C]*C/{next}//{print}'

যদি প্যাটার্নটির সাথে মেলে তবে লাইনটি এড়িয়ে যান, অন্যথায় এটি মুদ্রণ করুন। আপনার আসলে দরকার নেই {print}, আপনি ব্যবহার করতে পারেন //এবং ডিফল্ট মুদ্রণ করতে পারেন , তবে আমি মনে করি এটির স্পষ্টর বানান।

আমার প্রথম চিন্তাটি egrep -vএকই ধাঁচের সাথে ব্যবহার করা ছিল , তবে এটি আসলে উত্থাপিত প্রশ্নের উত্তর দেয় না।


1
এর পরে কোন কিছুর মিল আছে {next}? শুধু বলুন awk '/pattern/ {next} 1'এবং প্যাটার্নের সাথে মেলে না এমন সমস্ত লাইন মুদ্রণ করা হবে। বা, আরও ভাল, awk '!/pattern/'সরাসরি এগুলি মুদ্রণের জন্য।
ফেডোরকুই

@ ফেডরকিই সম্পর্কে ভাল পয়েন্ট !/pattern/(যা কোনওভাবে আমার মন কেড়ে নিয়েছিল ) তবে আমি //{print}একটি ক্রিপ্টিকের চেয়ে স্ব- বর্ণনামূলক দেখতে চাই 1। এটিকে গুরুতরভাবে কম দক্ষ বা কার্যকর না করার সাথে সামঞ্জস্য রেখে আপনার কোড বজায় রাখতে পরবর্তী ব্যক্তির থেকে ন্যূনতম যোগ্যতা এবং সাবলীলতা ধরে করুন।
নিগেল 222
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.