বিভিন্ন লাইনে ফাইলের একাধিক স্ট্রিংয়ের জন্য গ্রেপ (যেমন পুরো ফাইল, লাইন ভিত্তিক অনুসন্ধান নয়)?


85

আমি ব্যবহারযোগ্য রিটার্নকোড সহ শব্দগুলি Dansk, Svenskaবা Norskযে কোনও লাইনে থাকা ফাইলগুলির জন্য গ্রেপ করতে চাই (যেহেতু আমি কেবল স্ট্রিংগুলি অন্তর্ভুক্ত রয়েছে এমন তথ্য পেতে চাই, আমার ওয়ান-লাইনারটি এর পরে আরও খানিকটা এগিয়ে যায়)।

আমার কাছে এগুলির মতো লাইনযুক্ত অনেকগুলি ফাইল রয়েছে:

Disc Title: unknown
Title: 01, Length: 01:33:37.000 Chapters: 33, Cells: 31, Audio streams: 04, Subpictures: 20
        Subtitle: 01, Language: ar - Arabic, Content: Undefined, Stream id: 0x20, 
        Subtitle: 02, Language: bg - Bulgarian, Content: Undefined, Stream id: 0x21, 
        Subtitle: 03, Language: cs - Czech, Content: Undefined, Stream id: 0x22, 
        Subtitle: 04, Language: da - Dansk, Content: Undefined, Stream id: 0x23, 
        Subtitle: 05, Language: de - Deutsch, Content: Undefined, Stream id: 0x24, 
(...)

আমি যা চাই তা এখানে সিউডোকোড:

for all files in directory;
 if file contains "Dansk" AND "Norsk" AND "Svenska" then
 then echo the filename
end

এই কাজ করতে সবচেয়ে ভালো উপায় কি? এটি কি এক লাইনে করা যায়?

উত্তর:


89

তুমি ব্যবহার করতে পার:

grep -l Dansk * | xargs grep -l Norsk | xargs grep -l Svenska

আপনি যদি গোপন ফাইলগুলিতে সন্ধান করতে চান তবে:

grep -l Dansk .* | xargs grep -l Norsk | xargs grep -l Svenska

চতুর সমাধান; একটি বিষয় লক্ষণীয় (সাধারণত বলছেন; ওপি যা চেয়েছিল তার সাথে প্রাসঙ্গিক নয়) হ'ল (ধারণাগত) ব্যর্থতার ক্ষেত্রেও সামগ্রিক প্রস্থান কোড 0 হবে । সুতরাং, যদি আপনি ব্যর্থতা বনাম সাফল্য নির্ধারণ করতে আগ্রহী হন, তবে আপনাকে স্টডআউট আউটপুট খালি কিনা তা পরীক্ষা করে দেখতে হবে বা এর পরিবর্তে @ এডস্টিলের পদ্ধতির নিয়োগ করা উচিত।
mklement0

@ এমকিলেমেন্ট: বাশ-এ PIPESTATUSঅ্যারেতে পাইপলাইনের সদস্যদের বহির্গমন মান রয়েছে।
ডেনিস উইলিয়ামসন

@ ডেনিস উইলিয়ামসন এটি জেনে রাখা ভাল, আপনাকে ধন্যবাদ আরেকটি বিকল্প হ'ল pipefail(অস্থায়ীভাবে) শেল বিকল্পটি চালু করা :shopt -so pipefail
এমকিলেমেন্ট 0

4
আপনি ব্যবহার করতে চাইতে পারেন grep -Zএবং xargs -0যদি আপনার ফাইলের নামগুলিতে স্পেস থাকতে পারে।
বেন চ্যালেঞ্জার

4
আপনার যদি অনেকগুলি ফাইল থাকে তবে এটি "তর্ক তালিকা খুব দীর্ঘ" ত্রুটির কারণ হতে পারে।
আনানফায়

23

কেবল বাশ এবং গ্রেপ ব্যবহারের অন্য একটি উপায়:

একটি একক ফাইলের জন্য 'test.txt':

  গ্রেপ-কিউ ডান্স্ক পরীক্ষা.টিএসটিএক্সটি && গ্রেপ-কিউ নর্স্ক পরীক্ষা

test.txtফাইলটি তিনটি (যে কোনও সংমিশ্রণে) সহ মুদ্রণ করবে । প্রথম দুটি গ্রেপ কোনও কিছু মুদ্রণ করে না ( -q) এবং শেষ দুটি কেবল প্রিন্ট করে যদি অন্য দুটি পাস করে passed

আপনি যদি ডিরেক্টরিটিতে প্রতিটি ফাইলের জন্য এটি করতে চান:

   জন্য f ইন *; গ্রেপ-কি ড্যান্স্ক-এফ && গ্রেপ-কিউ নর্স্ক $ ফ && গ্রেপ-এল স্বেঞ্জা $ চ; সম্পন্ন

তবে তারপরে 3 বার গ্রেপ চালানোর দরকার নেই।
কুড়ুমি

4
আমি জানি আপনি -e এর সাথে নিদর্শনগুলি একত্রিত করতে পারেন, তবে আমি একা গ্রেপের সাথে সংযোগ তৈরির উপায় দেখতে পেলাম না।
এড স্টিল

4
দুর্দান্ত; পুনরায় for f ...: এম্বেড থাকা ফাঁকা স্থানগুলি সহ ফাইলের নামগুলি সঠিকভাবে পরিচালনা করা হয়েছে তা নিশ্চিত করার "$f"পরিবর্তে (ডাবল-কোটিং) ব্যবহার করুন $f
mklement0

@ ভিএমপিস্ট্রি-র উপর এই পদ্ধতির সুবিধা হ'ল প্রস্থান কোডটি সঠিকভাবে প্রতিফলিত করে যেগুলি অনুসন্ধানের সমস্ত পদ খুঁজে পেয়েছে কিনা।
mklement0

19
grep –irl word1 * | grep –il word2 `cat -` | grep –il word3 `cat -`
  • -i অনুসন্ধান কেসকে সংবেদনশীল করে তোলে
  • -r ফোল্ডারগুলির মাধ্যমে ফাইল অনুসন্ধানকে পুনরাবৃত্ত করে তোলে
  • -l শব্দটি পাওয়া ফাইলগুলির সাথে পাইপগুলি পাইপ করে
  • cat - পরবর্তী গ্রেপ এর তালিকাতে পাস করা ফাইলগুলির মাধ্যমে দেখার কারণ করে to

4
এটি সহজ এবং সর্বাধিক সহজ উত্তর, খুব সহায়ক ধন্যবাদ!
মজিক

9

বিভিন্ন লাইনে ফাইলের একাধিক স্ট্রিংয়ের জন্য কীভাবে গ্রেপ করবেন (পাইপ প্রতীকটি ব্যবহার করুন):

for file in *;do 
   test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file
done

মন্তব্য:

  1. আপনি যদি ""আপনার গ্রেপের সাথে ডাবল উদ্ধৃতি ব্যবহার করেন তবে আপনাকে পাইপটি এড়িয়ে চলতে হবে: \|ডান্স্ক, নর্স্ক এবং স্বেস্তকাকে অনুসন্ধান করতে।

  2. ধরে নেওয়া যায় যে একটি লাইনের একটি মাত্র ভাষা আছে।

ওয়াকথ্রু: http://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/


ড্যানস্ক নর্স্ক এবং স্বেস্তকা সকলেই একই লাইনে উপস্থিত হলে তা ব্যর্থ হবে না?
ভিএমপিস্ট্র

হ্যাঁ। এই ক্ষেত্রে ব্যর্থ হবে। আমি ধরে নিয়েছি যে প্রতি লাইনগুলিতে ভাষাগুলি একটি করে উপস্থিত হয়।
দামোদরন আর

আমার কাছে থাকলে কেবল Norskতিনটি লাইনে ফাইল করা হত ।
বেনিয়ামিন ডব্লিউ

6

আপনি খুব সহজেই এসকে দিয়ে এটি করতে পারেন :

ack -l 'cats' | ack -xl 'dogs'
  • -l: ফাইলগুলির একটি তালিকা ফেরত দিন
  • -x: STDIN (পূর্ববর্তী অনুসন্ধান) থেকে ফাইলগুলি নিন এবং কেবল সেই ফাইলগুলি অনুসন্ধান করুন

আপনি যতক্ষণ না চান ফাইলগুলি না পাওয়া পর্যন্ত আপনি কেবল পাইপিং চালিয়ে যেতে পারেন।


যখন আমি এটি চেষ্টা করি, এটি বলে Unknown option: x। এস্কের একটি নির্দিষ্ট সংস্করণ রয়েছে যা এই এক্স পতাকাটিকে সমর্থন করে?
হাসান

4
awk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print "0" }' 

তারপরে আপনি শেলের সাহায্যে রিটার্ন মানটি ধরতে পারেন

আপনার যদি রুবি থাকে (1.9+)

ruby -0777 -ne 'print if /Dansk/ and /Norsk/ and /Svenka/' file

4
আপনার if (a && b && c) {exit 0} else {exit 1}exit !(a && b && c)
অবাস্তব অবশেষে

আপনার রুবি সমাধানটি সঠিক দেখাচ্ছে না। এটি কেবলমাত্র অনুচ্ছেদে মুদ্রণ করবে যাতে সমস্ত অনুসন্ধানের শব্দ থাকে। প্রশ্নটি হ'ল: ফাইলটি (সামগ্রিকভাবে) সমস্ত শব্দ ধারণ করে, এমনকি যদি সেগুলি সমস্ত একই অনুচ্ছেদে প্রদর্শিত না হয়।
গ্লেন জ্যাকম্যান

ধন্যবাদ পুরো ফাইলটি প্রয়োজন হলে পরিবর্তিত হয়েছে, তবে -0777
কুড়ুমী

4

এটি একাধিক ফাইলে একাধিক শব্দ অনুসন্ধান করে:

egrep 'abc|xyz' file1 file2 ..filen 

4
উভয় স্ট্রিং রয়েছে এমন ফাইলগুলি সন্ধানের পাশাপাশি এটি 'abc' বা 'xyz' ফাইলগুলিও খুঁজে পাবে। আমি মনে করি ওপি ফাইলগুলিতে 'আবসি' এবং 'এক্সওয়াইজেড' চেয়েছিল।
ক্রিস ওয়ার্থ

3

কেবল:

grep 'word1\|word2\|word3' *

দেখতে এই পোস্টে আরও তথ্যের জন্য


আমি -lপতাকাটি যুক্ত করব, তবে এর বাইরে, এই উত্তরটি আমার কাছে সবচেয়ে সোজা মনে হয়, যদি না আমি কিছু মিস করি।
xdmoore

হ্যাঁ, আপনি একাধিক পাইপ এবং ফিল্টারগুলির মধ্যে সমস্ত ডেটা প্রক্রিয়া না করার কারণে এটি আরও কার্যকর
মোশি বিরি

4
প্রশ্নটি এমন একটি অভিব্যক্তি সম্পর্কে জিজ্ঞাসা করে যা তিনটি শর্তাবলীযুক্ত ফাইলগুলি ফেরত দেয়; এটি তিনটি যে কোনও (তিনটির পরিবর্তে) যুক্ত লাইনগুলি (ফাইলের পরিবর্তে) প্রদান করে।
বেনিয়ামিন ডাব্লু।

2

এটি গ্লেন জ্যাকম্যান এবং কুরুমির উত্তরগুলির মিশ্রণ যা স্থির শব্দের একটি স্বেচ্ছাসেবী সংখ্যার পরিবর্তে বা রেগেক্সের একটি নির্দিষ্ট সেটের পরিবর্তে একটি স্বেচ্ছাসেবী সংখ্যার অনুমতি দেয়।

#!/usr/bin/awk -f
# by Dennis Williamson - 2011-01-25

BEGIN {
    for (i=ARGC-2; i>=1; i--) {
        patterns[ARGV[i]] = 0;
        delete ARGV[i];
    }
}

{
    for (p in patterns)
        if ($0 ~ p)
            matches[p] = 1
            # print    # the matching line could be printed
}

END {
    for (p in patterns) {
        if (matches[p] != 1)
            exit 1
    }
}

এটি এইভাবে চালান:

./multigrep.awk Dansk Norsk Svenska 'Language: .. - A.*c' dvdfile.dat

2

এখানে আমার জন্য ভাল কাজ করেছে:

find . -path '*/.svn' -prune -o -type f -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \;
./path/to/file1.sh
./another/path/to/file2.txt
./blah/foo.php

আমি যদি এই তিনটির সাথে .sh ফাইলগুলি সন্ধান করতে চাইতাম তবে আমি ব্যবহার করতে পারতাম:

find . -path '*/.svn' -prune -o -type f -name "*.sh" -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \;
./path/to/file1.sh

1

@ কুড়ুমির উত্তম উত্তরে সম্প্রসারণ, এখানে একটি বাশ ফাংশন রয়েছে:

all_word_search() {
    gawk '
        BEGIN {
            for (i=ARGC-2; i>=1; i--) {
                search_terms[ARGV[i]] = 0;
                ARGV[i] = ARGV[i+1];
                delete ARGV[i+1];
            }
        }
        {
            for (i=1;i<=NF; i++) 
                if ($i in search_terms) 
                    search_terms[$1] = 1
        }
        END {
            for (word in search_terms) 
                if (search_terms[word] == 0) 
                    exit 1
        }
    ' "$@"
    return $?
}

ব্যবহার:

if all_word_search Dansk Norsk Svenska filename; then
    echo "all words found"
else
    echo "not all words found"
fi

1

আমি দুটি পদক্ষেপ নিয়ে তা করেছি। এক পৃষ্ঠায় সিএসভি ফাইলের একটি তালিকা তৈরি করুন এই পৃষ্ঠার মন্তব্যের সাহায্যে আমি আমার যা প্রয়োজন তা পেতে দুটি স্ক্রিপ্টহীন পদক্ষেপ নিয়েছি। টার্মিনালটিতে কেবল টাইপ করুন:

$ find /csv/file/dir -name '*.csv' > csv_list.txt
$ grep -q Svenska `cat csv_list.txt` && grep -q Norsk `cat csv_list.txt` && grep -l Dansk `cat csv_list.txt`

এটি আমার যা প্রয়োজন ঠিক তা করেছে - তিনটি শব্দ সম্বলিত ফাইলের নাম মুদ্রণ করুন।

মত প্রতীক মনে রাখবেন `' "


1

আপনার যদি কেবল দুটি অনুসন্ধানের শব্দ প্রয়োজন হয় তবে যুক্তিযুক্তভাবে সর্বাধিক পঠনযোগ্য পদ্ধতিটি প্রতিটি অনুসন্ধান চালানো এবং ফলাফলগুলি ছেদ করা:

 comm -12 <(grep -rl word1 . | sort) <(grep -rl word2 . | sort)

1

আপনি যদি গিট ইনস্টল করা আছে

git grep -l --all-match --no-index -e Dansk -e Norsk -e Svenska

--No-index বর্তমান ডিরেক্টরিতে ফাইলগুলি অনুসন্ধান করে যা গিট দ্বারা পরিচালিত নয়। সুতরাং এই কমান্ডটি কোনও ডিরেক্টরিতে কাজ করবে এটি নির্বিশেষে এটি গিট সংগ্রহস্থল কিনা।


0

আমার আজ এই সমস্যা ছিল, এবং এখানকার সমস্ত ওয়ান-লাইনার আমার কাছে ব্যর্থ হয়েছিল কারণ ফাইলগুলির নামগুলিতে স্পেস রয়েছে।

আমি এই কাজটি নিয়ে এসেছি:

grep -ril <WORD1> | sed 's/.*/"&"/' | xargs grep -il <WORD2>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.