গ্রেপ সহ, আমি কীভাবে কোনও প্যাটার্নটি মেলে এবং অন্য প্যাটার্নটির সাথে মেলে ফেলতে পারি?


11

এর সাথে grep, আমি সমস্ত লাইন নির্বাচন করতে চাই যা কোনও প্যাটার্নের সাথে মেলে এবং এটি অন্য প্যাটার্নের সাথে মেলে না। আমি এর একক অনুরোধটি ব্যবহার করতে সক্ষম হতে চাই grepযাতে আমি --after-contextবিকল্পটি (বা --before-context, বা --context) ব্যবহার করতে পারি ।

-vএখানে grepব্যবহারযোগ্য নয়, কারণ এটি -eবিকল্পটি ব্যবহার করে আমি যে সমস্ত প্যাটার্নগুলি দিয়েছি তা এড়িয়ে যায় ।

উদাহরণ

আমি নীচের প্রসঙ্গের এক লাইনের সাথে needleমিলিয়ে যাওয়া লাইনের সাথে মিল রেখে লাইনগুলি অনুসন্ধান করতে চাই ignore me

আমার ইনপুট ফাইলটি এখানে:

one needle ignore me
two
three
four needle
five

আমি যে আউটপুটটি চাই তা হ'ল:

four needle
five

আপনি দেখতে পাচ্ছেন যে এই নিষ্পাপ সমাধানটি কাজ করে না:

$ cat file | grep --after-context=1 needle | grep -v 'ignore me'
two
---
four needle
five

উত্তর:


10

আপনার যদি জিএনইউ গ্রেপ থাকে তবে আপনি পার্ল নিয়মিত এক্সপ্রেশন ব্যবহার করতে পারেন , যার একটি অবহেলা গঠন রয়েছে

grep -A1 -P '^(?!.*ignore me).*needle'

আপনার যদি জিএনইউ গ্রেপ না থাকে তবে আপনি এর আগে / পরে প্রাসঙ্গিক বিকল্পগুলি এমওকে তে অনুকরণ করতে পারেন ।

awk -v after=3 -v before=2 '
/needle/ && !/ignore me/ {
    for (i in h) {
        print h[i];
        delete h[i];
    }
    until = NR + after;
}
{
    if (NR <= until) print $0; else h[NR] = $0;
    delete h[NR-before];
}
END {exit !until}
'

8

আপনি GNU ব্যবহার করছেন বলে মনে হচ্ছে । জিএনইউ --perl-regexগ্রেপ সহ, আপনি পিসিআরই সক্রিয় করতে পতাকাটিতে পাস করতে পারেন এবং তারপরে নীচের উদাহরণ হিসাবে একটি নেতিবাচক বর্ণনামূলক বক্তব্য সরবরাহ করতে পারেন

grep --after-context=1 \
--perl-regex '^(?:(?!ignore me).)*needle(?:(?!ignore me).)*$' file.txt
four needle
five

নোট প্রধান বিষয় এখানে যে (?:(?!STRING).)*হয় STRINGযেমন [^CHAR]*হয়CHAR


@ 1_সিআর ... স্যার .. এটি দুর্দান্ত ... .. হাসির কিছু পিack
রাহুল পাতিল

@RahulPatil। :-), হ্যাঁ জিএনইউ গ্রেপ এটি ভাল।
iruvar

এটি আমি যা চাই তা পুরোপুরি নয়। "সুই" এর আগে বা পরে "আমাকে উপেক্ষা করুন" কিনা তা আমি কাজ করতে চাই।
ফ্লিম

@ রাহুলপাতিল, ধন্যবাদ, আমি এটিকে সর্বশেষ সংস্করণে ঠিক করেছি
ir:১:

খুব দরকারী. বিশেষত প্রেক্ষাপটের সাথে গ্রেপের ক্ষেত্রে যেখানে আপনি নিখুঁতভাবে মিলে যাওয়া লাইনগুলি বাদ দিতে চান তবে প্যাটার্নের একটি নির্দিষ্ট অংশ ছাড়াই। মূল প্রশ্নের কাছাকাছি কিন্তু একেবারে একরকম নয়।
গাইঠে

2

আমি এর পরিবর্তে awk ব্যবহার করার পরামর্শ দেব কারণ এটি মাল্টি-লাইন আইওকে আরও ভালভাবে পরিচালনা করে। হয় 1) ফলাফল --\nরেকর্ড বিভাজক হিসাবে জিএনইউ কর্কগুলিতে পাইপ করুন , বা 2) ম্যাচিংয়ের সবকটি খালি জায়গায় করুন।

বিকল্প 1

<file grep -A1 needle | awk '!/ignore me/' RS='--\n' ORS='--\n'

আউটপুট:

four needle                                                                                  
five
--

দ্রষ্টব্য, এই বিকল্পটি কেবল প্রথম লাইনের সাথে তুলনা করার জন্য পুরো রেকর্ডটি ignore meসেট করে FS=1এবং এর সাথে মেলে $1

বিকল্প 2

<file awk 'a-- > 0; $0 ~ re1 && $0 !~ re2 { print $0; a=after }' re1=needle re2='ignore me' after=1

ignore meফাইলটিতে কি তখন একাধিক , অদ্ভুত কাজ করে না
রাহুল পাটিল

@ রাহুলপাতিল: আপনি কি আপনার প্রশ্নে পুনরায় ব্যাখ্যা করতে বা আরও বিশদ যুক্ত করতে পারবেন? আমি কি বুঝতে চাইছি বুঝতে পারছি না।
থোর

@ এই ইনপুট ফাইলের সাহায্যে
রাহুল পাতিল

@ রাহুলপাতিল: আমি আপনার এখনকার অর্থটি দেখতে পাচ্ছি, বিকল্প 1 অনুমান করে যে --\nপ্রতিটি মিলিত গোষ্ঠীর মধ্যে একটি ডিলিমিটার রয়েছে, গ্রুপগুলি একে অপরের সাথে সংলগ্ন থাকলে সেখানে নেই। সংলগ্ন গ্রুপগুলি কীভাবে পরিচালনা করা উচিত তা কার্য-নির্দিষ্ট, তাই এটি অগত্যা ভুল নয়। বিকল্প 2 বিভাজকের উপর নির্ভর করে না এবং প্রভাবিত হয় না।
থোর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.