আমি দুটি শব্দ দুটি যুক্ত করে রেখার জন্য কীভাবে গ্রেপ করব?


25

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

এখনও অবধি চেষ্টা করেছি grep pattern1 | grep pattern2 | ...কিন্তু ফলস্বরূপ আমি প্রত্যাশা করি নি।


(1) আপনি "শব্দ" এবং "নিদর্শন" সম্পর্কে কথা বলেন। ইহা কোনটা? "দ্রুত", "বাদামী" এবং "শিয়াল" এর মতো সাধারণ শব্দগুলি, বা নিয়মিত প্রকাশের মতো [a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+? (২) কোনও শব্দ / নিদর্শনগুলির মধ্যে একটি যদি এক লাইনে একাধিকবার উপস্থিত হয় (এবং অন্যটি প্রকাশিত হয় না) তবে কী হবে? শব্দের সাথে কি এটি একবার উপস্থিত হয়, বা এটি একাধিক ঘটনা হিসাবে গণ্য হয়?
জি-ম্যান

উত্তর:


59

ছাড়া অন্য একটি সরঞ্জাম grepহ'ল উপায়।

পার্ল ব্যবহার করে, উদাহরণস্বরূপ, আদেশটি হ'ল:

perl -ne 'print if /pattern1/ xor /pattern2/'

perl -neস্টিডিনের প্রতিটি লাইনের উপরে প্রদত্ত কমান্ডটি চালায়, যা এই ক্ষেত্রে লাইনটি মেলে যদি এটি প্রিন্ট করে তবে /pattern1/ xor /pattern2/অন্য কথায় একটি প্যাটার্নের সাথে মেলে তবে অন্যটি (একচেটিয়া বা) নয়।

এটি উভয় ক্রমে প্যাটার্নটির জন্য কাজ করে এবং এর একাধিক আহ্বানের চেয়ে ভাল পারফরম্যান্স হওয়া উচিত grepএবং পাশাপাশি টাইপিংও কম।

বা, আরও কম সংক্ষেপে:

awk 'xor(/pattern1/,/pattern2/)'

বা বিশ্রী সংস্করণের জন্য যা নেই xor:

awk '/pattern1/+/pattern2/==1`

4
খুব ভাল - xorকেবল জিএনইউ অ্যাওক- এ কি আউক পাওয়া যায়?
স্টিল্ড্রাইভার

9
@ স্টিলড্রাইভার আমি মনে করি এটি কেবল জিএনইউ, হ্যাঁ। বা কমপক্ষে এটি পুরানো সংস্করণগুলি থেকে অনুপস্থিত। আপনি এটি প্রতিস্থাপন করতে পারবেন /pattern1/+/pattern2/==1আইআর xorঅনুপস্থিত।
ক্রিস

4
@JimL। আপনি \bনিজেরাই নিদর্শনগুলিতে শব্দের গণ্ডি ( ) স্থাপন করতে পারেন \bword\b
wjandrea

4
@ লাইকিংস্টিভ আপনি যদি বিশেষভাবে গ্রেপ ব্যবহার করতে চান তবে এখানে প্রচুর অন্যান্য উত্তর রয়েছে। তবে যে সমস্ত লোকেরা কেবল কাজটি সম্পাদন করতে চান তাদের পক্ষে আরও ভালভাবে জেনে রাখা ভাল যে আরও কিছু সরঞ্জাম রয়েছে যা গ্রেপ যা করতে পারে তা করতে পারে তবে আরও এবং আরও সহজেই।
ক্রিস

3
@vikingsteve আমি দৃঢ়ভাবে মনে হবে যে একটি, grep সমাধান চাহিদা XY সমস্যা এক ধরনের
হ্যাগেন ভন Eitzen

30

জিএনইউ দিয়ে grepআপনি উভয় শব্দ পাস করতে পারেন grepএবং তারপরে উভয় নিদর্শন যুক্ত লাইনগুলি সরিয়ে ফেলতে পারেন।

$ cat testfile.txt
abc
def
abc def
abc 123 def
1234
5678
1234 def abc
def abc

$ grep -w -e 'abc' -e 'def' testfile.txt | grep -v -e 'abc.*def' -e 'def.*abc'
abc
def

16

দিয়ে চেষ্টা করুন egrep

egrep  'pattern1|pattern2' file | grep -v -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'

3
এছাড়াও হিসেবে লেখা যেতে পারেgrep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'
গ্লেন জ্যাকম্যান

8
এছাড়াও, Direct invocation as either egrep or fgrep is deprecatedgrep -E
গ্রেপ

এটি আমার ওএসে নেই @glennjackman
গ্রাম্প

1
@ গ্রাম্প সত্যি? ওএস কি? এমনকি পসিক্স উল্লেখ করেছে যে গ্রেপের উচিত -fএবং -eঅপশন থাকা উচিত যদিও এটি পুরানো egrepএবং কিছু fgrepসময়ের জন্য সমর্থন অব্যাহত থাকবে।
টেরডন

1
@terdon, POSIX POSIX ইউটিলিটির পথ নির্দিষ্ট করে না। আবার, সেখানে মান grep(যে সমর্থন -F, -E, -e, -fPOSIX প্রয়োজন হিসাবে) হয় /usr/xpg4/bin। এতে থাকা ইউটিলিটিগুলি /binপুরানো anti
স্টাফেন চেজেলাস

12

grepপার্ল-জাতীয় নিয়মিত এক্সপ্রেশন (যেমন pcregrepবা জিএনইউ বা অ্যাস্ট-ওপেন grep -P) সমর্থন করে এমন বাস্তবায়নগুলি সহ , আপনি এটি একটি grepনিমন্ত্রণে এটি করতে পারেন :

grep -P '^(?=.*pat1)(?!.*pat2)|^(?=.*pat2)(?!.*pat1)'

যে লাইন যে মিল খুঁজে হয় pat1কিন্তু pat2, অথবা pat2কিন্তু pat1

(?=...)এবং (?!...)যথাক্রমে অপারেটরগুলি এগিয়ে এবং নেতিবাচক চেহারা হয়। তাই টেকনিক্যালি, বিষয় (শুরুতে জন্য উপরের সৌন্দর্য ^) প্রদান করা এটি দ্বারা অনুসৃত হচ্ছে .*pat1এবং অনুসরণ না .*pat2বা, সঙ্গে একই pat1এবং pat2বিপরীত।

উভয় নিদর্শন রয়েছে এমন রেখাগুলির জন্য এটি সাবজেক্টিমাল যা সেগুলি পরে দু'বার সন্ধান করা হবে। আপনি পরিবর্তে আরও উন্নত পার্ল অপারেটর ব্যবহার করতে পারেন:

grep -P '^(?=.*pat1|())(?(1)(?=.*pat2)|(?!.*pat2))'

(?(1)yespattern|nopattern)এর সাথে মেলে yespatternযদি 1স্ট্যান্ড ক্যাপচার গ্রুপটি ( ()উপরে খালি ) মিলছে এবং nopatternঅন্যথায়। যদি এটি ()মেলে তবে এর অর্থ pat1মেলে না, তাই আমরা সন্ধান করি pat2(সামনের দিকে ইতিবাচক চেহারা) এবং আমরা অন্যথায় নয় pat2 ( সামনে ইতিবাচক চেহারা) খুঁজছি।

সহ sed, আপনি এটি লিখতে পারেন:

sed -ne '/pat1/{/pat2/!p;d;}' -e '/pat2/p'

আপনার প্রথম সমাধানটি grep: the -P option only supports a single patternকমপক্ষে প্রতিটি সিস্টেমে আমার অ্যাক্সেস রয়েছে এতে ব্যর্থ। যদিও আপনার দ্বিতীয় সমাধানের জন্য +1।
ক্রিস

1
ক্রিস, আপনি ঠিক বলেছেন এটি জিএনইউ-র নির্দিষ্ট সীমাবদ্ধ বলে মনে হয় greppcregrepএবং অ্যাস্ট-ওপেন গ্রেপ এর সমস্যা নেই। আমি -eবিকল্প আরআর অপারেটরের সাথে একাধিক প্রতিস্থাপন করেছি , সুতরাং এটি grepএখন GNU এর সাথেও কাজ করা উচিত ।
স্টাফেন চেজেলাস

হ্যাঁ, এটি এখন ভাল কাজ করে।
ক্রিস

3

বুলিয়ান পদগুলিতে, আপনি একটি xor বি খুঁজছেন, যা হিসাবে লেখা যেতে পারে

(এ এবং বি নয়)

অথবা

(খ এবং এ নয়)

প্রদত্ত যে আপনার প্রশ্নটিতে উল্লেখ করা হয়নি যে আপনি যতক্ষণ না মিলে যাওয়া লাইনগুলি দেখানো হচ্ছে আউটপুট ক্রমের সাথে জড়িত রয়েছেন, A xor B এর বুলিয়ান বিস্তৃতিটি গ্রেপ-এ খুব সুন্দর রঙিন:

$ cat << EOF > foo
> a b
> a
> b
> c a
> c b
> b a
> b c
> EOF
$ grep -w 'a' foo | grep -vw 'b'; grep -w 'b' foo | grep -vw 'a';
a
c a
b
c b
b c

1
এটি কাজ করে তবে এটি ফাইলের ক্রমকে ফাঁকি দেবে।
স্পারহাক

@ স্পারহাক সত্য, যদিও "স্ক্যামাবল" একটি কঠোর শব্দ is ;) এটি প্রথমে সমস্ত 'ক' ম্যাচ তালিকাবদ্ধ করে, ক্রমে, তারপরে সমস্ত 'বি' ম্যাচগুলি ক্রমানুসারে। ওপি অর্ডার বজায় রাখতে কোনও আগ্রহ প্রকাশ করেনি, কেবল লাইনগুলি দেখান। FAWK, পরবর্তী পদক্ষেপ হতে পারে sort | uniq
জিম এল।

মেলা কল; আমি সম্মত হই যে আমার ভাষাটি ভুল ছিল না। আমি বোঝাতে চেয়েছিলাম যে আসল ক্রমটি পরিবর্তন করা হবে।
স্পারহাক

1
@ স্পারহাক ... এবং আমি সম্পূর্ণ প্রকাশের জন্য আপনার পর্যবেক্ষণে সম্পাদনা করেছি।
জিম এল।

-2

নিম্নলিখিত উদাহরণের জন্য:

# Patterns:
#    apple
#    pear

# Example line
line="a_apple_apple_pear_a"

এই বিশুদ্ধরূপে সঙ্গে কাজ করা যেতে পারে grep -E, uniqএবং wc

# Grep for regex pattern, sort as unique, and count the number of lines
result=$(grep -oE 'apple|pear' <<< $line | sort -u | wc -l)

যদি grepপার্ল নিয়মিত প্রকাশের সাথে সংকলিত হয় তবে আপনি এখানে পাইপ লাগানোর পরিবর্তে শেষ ঘটনাটিতে মিল করতে পারেন uniq:

# Grep for regex pattern and count the number of lines
result=$(grep -oP '(apple(?!.*apple)|pear(?!.*pear))' <<< $line | wc -l)

ফলাফল আউটপুট:

# Only one of the words exists if the result is < 2
((result > 0)) &&
   if (($result < 2)); then
      echo Only one word matched
   else
      echo Both words matched
   fi

একটি এক-লাইনার:

(($(grep -oP '(apple(?!.*apple)|pear(?!.*pear))' <<< $line | wc -l) == 1)) && echo Only one word matched

আপনি যদি প্যাটার্নটিকে হার্ড-কোড করতে না চান, তবে এটিকে উপাদানগুলির একটি পরিবর্তনশীল সেট সহ একত্রিত করে একটি ফাংশন দিয়ে স্বয়ংক্রিয় করা যেতে পারে।

এটি পাইপে বা অতিরিক্ত প্রক্রিয়াবিহীন কোনও ফাংশন হিসাবে বাশ-এ স্থানীয়ভাবে করা যেতে পারে তবে এতে আরও জড়িত থাকবেন এবং সম্ভবত আপনার প্রশ্নের ক্ষেত্রের বাইরে।


(1) আমি ভাবছিলাম যখন কেউ পার্ল নিয়মিত এক্সপ্রেশন ব্যবহার করে কোনও উত্তর দিতে চলেছে। আপনি যদি আপনার পোস্টের সেই অংশটির দিকে মনোনিবেশ করে থাকেন এবং কীভাবে এটি কাজ করে তা ব্যাখ্যা করে থাকেন তবে এটি একটি ভাল উত্তর হতে পারে। (২) তবে আমি ভয় করি বাকিটা এতটা ভাল না। প্রশ্নটি বলেছে " দুটি শব্দ দুটিতেই কেবল লাইনগুলি দেখান " (জোর দেওয়া হয়েছে)। যদি আউটপুটটি লাইন হওয়ার কথা বলে , তবে এটির কারণ দাঁড়ায় যে ইনপুটটিও একাধিক লাইন হতে হবে   কিন্তু আপনার পদ্ধতির কাজ করে শুধুমাত্র যখন শুধুমাত্র একটি একক লাইন দিকে তাকিয়ে। … (চালিয়ে যাওয়া)
জি-ম্যান

(Cont'd)… উদাহরণস্বরূপ, যদি ইনপুটটিতে লাইন থাকে Big apple\nএবং pear-shaped\n, তবে আউটপুটে both দুটি লাইন থাকা উচিত। আপনার সমাধান 2 একটি গণনা পেতে হবে; দীর্ঘ সংস্করণটি "উভয় শব্দের সাথে মিলেছে" (যা ভুল প্রশ্নের উত্তর report) এবং সংক্ষিপ্ত সংস্করণটি কিছুই বলবে না report (3) একটি পরামর্শ: -oএখানে ব্যবহার করা একটি সত্যই খারাপ ধারণা, কারণ এটি ম্যাচগুলি যুক্ত লাইনগুলি লুকিয়ে রাখে, তাই যখন উভয় শব্দ একই লাইনে প্রদর্শিত হয় আপনি দেখতে পারবেন না। … (চালিয়ে যাওয়া)
জি-ম্যান

(চালিয়ে যাওয়া) ... (4) নীচের লাইন: প্রতিটি লাইনে কেবল শেষ ঘটনাটি মেলে আপনার uniq/ sort -uএবং অভিনব পার্ল নিয়মিত অভিব্যক্তি এই প্রশ্নের কোনও কার্যকর উত্তর যুক্ত করতে পারে না। তবে, তারা তা করলেও এটি একটি খারাপ উত্তর হতে পারে কারণ আপনি প্রশ্নের উত্তর দেওয়ার ক্ষেত্রে তারা কীভাবে অবদান রাখছেন তা ব্যাখ্যা করেন না । ( একটি ভাল ব্যাখ্যার উদাহরণের জন্য স্টাফেন চ্যাজেলাসের উত্তর দেখুন ))
জি-ম্যান

ওপিতে বলা হয়েছে যে তারা "দুটি শব্দের একটি মাত্র লাইনই প্রদর্শন করতে চেয়েছিল" যার অর্থ প্রতিটি লাইনকে তার নিজেরাই মূল্যায়ন করতে হবে। আমি দেখতে পাচ্ছি না কেন আপনি কেন মনে করেন যে এটি প্রশ্নের উত্তর দেয় না। আপনি ব্যর্থ হবে বলে মনে করেন দয়া করে একটি উদাহরণ ইনপুট সরবরাহ করুন।
Zhro

ওহ, হয় যে আপনি যা বোঝাতে চাইছেন? “ইনপুট একবারে একটি লাইন পড়ুন এবং প্রতিটি লাইনের জন্য এই দুটি বা তিনটি কমান্ড কার্যকর করুন "? (1) এটি আপনি বোঝাতে চেয়েছিলেন তা বেদনাদায়কভাবে অস্পষ্ট। (2) এটি বেদনাদায়কভাবে অক্ষম। আপনার চারটি উত্তর আগে কীভাবে কয়েকটি কমান্ডে ( পুরো একটিকে, দুটি বা চারটি) পুরো ফাইলটি পরিচালনা করবেন তা দেখিয়েছিল এবং আপনি ইনপুটটির লাইন জন্য 3 commands n কমান্ড চালাতে চান  ? এমনকি যদি এটি কার্যকর হয় তবে এটি অযথা ব্যয়বহুল মৃত্যুদন্ড কার্যকর করার জন্য একটি ডাউন ভোট উপার্জন করে। (3) কেশ বিভক্ত হওয়ার ঝুঁকিতে, এটি এখনও উপযুক্ত লাইনগুলি দেখানোর কাজ করে না ।
জি-ম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.