পাঠ্য ফাইল থেকে লাইনগুলি নির্বাচন করুন যা অন্য কোনও ফাইলে আইডির তালিকাভুক্ত রয়েছে


13

আমি মাঝারি আকারের (প্রায় 10M-100M লাইন) ট্যাব-বিভাজিত কলাম পাঠ্য ফাইলগুলির সাথে কাজ করার জন্য আমার ইউনিক্স শেলটিতে প্রচুর গ্রেপ অ্যাওক সাজান্ট ব্যবহার করি। এই বিষয়ে ইউনিক্স শেলটি আমার স্প্রেডশিট।

তবে আমার একটি বিশাল সমস্যা আছে, তা হল আইডিগুলির একটি তালিকা দেওয়া রেকর্ড নির্বাচন করা।

রয়ে table.csvবিন্যাস ফাইল id\tfoo\tbar...এবং ids.csvআইডি একটি তালিকা সহ ফাইল, শুধুমাত্র থেকে রেকর্ড নির্বাচন table.csvমধ্যে ID উপস্থিত সঙ্গে ids.csv

/programming/13732295/extract-all-lines-from-text-file-based-on-a-given-list-of-ids এর ধরণ কিন্তু শেল দিয়ে, পার্ল নয়।

grep -Fআইডি ভেরিয়েবল প্রস্থ হলে স্পষ্টতই মিথ্যা ইতিবাচক উত্পাদন ঘটে। joinএমন একটি ইউটিলিটি যা আমি কখনই বুঝতে পারি না। প্রথমত, এর জন্য বর্ণমালা বাছাই করা দরকার (আমার ফাইলগুলি সাধারণত সংখ্যাগতভাবে বাছাই করা হয়) তবে তারপরেও আমি ভুল অর্ডার সম্পর্কে অভিযোগ না করে এবং কিছু রেকর্ড বাদ না দিয়ে এটিকে কাজ করতে পারি না। সুতরাং আমি এটি পছন্দ করি না। আইডির ^id\tসংখ্যা বড় হলে -s সহ ফাইলের বিরুদ্ধে গ্রেপ -f খুব ধীর হয়। awkকষ্টকর।

এর জন্য কি কোনও ভাল সমাধান আছে? ট্যাব-বিচ্ছিন্ন ফাইলগুলির জন্য কোনও নির্দিষ্ট সরঞ্জাম? অতিরিক্ত কার্যকারিতাও সবচেয়ে স্বাগত জানানো হবে।

ইউপিডি: সংশোধিত sort->join


যদি grep -fখুব মন্থর হয়, এই কৌশলটি বজায় রাখার পক্ষে এটি তার চেয়ে বেশি সমস্যার মতো মনে হচ্ছে - বৈচিত্রগুলি সম্ভবত একই ও (এন * এম) পারফরম্যান্স ইস্যুগুলির শিকার হবে। আপনার সময়টি কীভাবে একটি সাধারণীকৃত এসকিউএল ডিবি ব্যবহার করতে হবে তা শেখার জন্য আরও ভাল সময় কাটানো হতে পারে ...
স্বর্ণলোকস

1
আপনি যে প্রশ্নটি যুক্ত করেছেন তা থেকে কেন পার্ল স্ক্রিপ্ট ব্যবহার করবেন না? বিকল্পভাবে, এটিতে অনুরূপ স্ক্রিপ্ট লেখা সম্ভব হবে awk
সিজেএম

বাশ 4 এ সংযুক্তিযুক্ত অ্যারে রয়েছে যা আপনাকে নেস্টেড লুপগুলি একটি লা পার্ল উদাহরণটি থেকে দূরে রাখতে হবে।
স্বর্ণলোক

1
sortসমস্ত ধরণের বাছাই, সংখ্যা, বর্ণমালা এবং অন্যান্য করতে পারে others দেখুন man sort
টেরডন

আমার এখানে একটি প্রশ্ন রয়েছে, আমরা যেখানে একই

উত্তর:


19

আমার ধারণা আপনি বোঝাতে চেয়েছিলেন grep -fনা grep -Fতবে আপনার উভয়ের সংমিশ্রণের দরকার আছে এবং -w:

grep -Fwf ids.csv table.csv

আপনি মিথ্যা ধনাত্মক হওয়ার কারণটি হ'ল (আমার ধারণা, আপনি ব্যাখ্যা করেননি) কারণ যদি কোনও আইডি অন্যটিতে থাকতে পারে তবে উভয়ই মুদ্রিত হবে। -wএই সমস্যাটি সরিয়ে দেয় এবং -Fনিশ্চিত করে যে আপনার নিদর্শনগুলি স্ট্রিং হিসাবে বিবেচিত হবে, নিয়মিত প্রকাশ নয়। থেকে man grep:

   -F, --fixed-strings
          Interpret PATTERN as a  list  of  fixed  strings,  separated  by
          newlines,  any  of  which is to be matched.  (-F is specified by
          POSIX.)
   -w, --word-regexp
          Select  only  those  lines  containing  matches  that form whole
          words.  The test is that the matching substring must  either  be
          at  the  beginning  of  the  line,  or  preceded  by  a non-word
          constituent character.  Similarly, it must be either at the  end
          of  the  line  or  followed by a non-word constituent character.
          Word-constituent  characters  are  letters,  digits,   and   the
          underscore.

   -f FILE, --file=FILE
          Obtain  patterns  from  FILE,  one  per  line.   The  empty file
          contains zero patterns, and therefore matches nothing.   (-f  is
          specified by POSIX.)

যদি আপনার মিথ্যা ইতিবাচক কারণ হ'ল কোনও আইডি কোনও নন-আইডি ক্ষেত্রে উপস্থিত হতে পারে তবে পরিবর্তে আপনার ফাইলটি লুপ করুন:

while read pat; do grep -w "^$pat" table.csv; done < ids.csv

বা, দ্রুত:

xargs -I {} grep "^{}" table.csv < ids.csv

ব্যক্তিগতভাবে, আমি perlযদিও এটি করতে হবে :

perl -lane 'BEGIN{open(A,"ids.csv"); while(<A>){chomp; $k{$_}++}} 
            print $_ if defined($k{$F[0]}); ' table.csv

1
+1 তবে: যদি আইডি কলামে ঠিক নয়, তবে সম্ভাব্য মিথ্যা ধনাত্মক আইডিটির সাথে শব্দের ভিত্তিতে মিল রয়েছে? আপনি যদি ^-F এর সাথে ব্যবহার না করতে পারেন তবে আপনি প্রথম কলামটি বিশেষভাবে লক্ষ্যবস্তু করতে পারবেন না।
স্বর্ণলোক

@ গোল্ডলোকস যদি ঠিক মিলে যায় তবে তারা মিথ্যা ধনাত্মক নয়। আপনি যা বলতে চাইছেন তা আমি পেয়েছি তবে সেই ক্ষেত্রে, ওপিকে তাদের ইনপুট ফাইলগুলি দেখানো উচিত।
টেরডন

^id\tওপি থেকে বিট বোঝা idঅন্য কলামে ঘটতে পারে। যদি না হয়, এটি কোনও ব্যাপার নয়।
স্বর্ণলোক

@ গোল্ডিলোকস ফেয়ার পয়েন্ট, উত্তর সম্পাদিত।
টেরডন

আমরা যেভাবে এটি ব্যবহার করতাম তা হ'ল অস্থায়ী ফাইল তৈরি করা (অ্যাজক বা সেড ব্যবহার করে) যা একটি অনন্য অক্ষর যুক্ত করেছিল (বলুন, কন্ট্রোল-এ) আমরা যে ক্ষেত্রটি সন্ধান করতে চাইছিলাম তা সীমিত করে, তারপরে গ্রেপ-এফ -f টেম্পাপ্টার্নফাইলে টেম্পারেটফিল ব্যবহার করুন | tr -d '\ 001'
মার্ক প্লটনিক

7

joinউপযোগ কি আপনি চান হয়। এর জন্য ইনপুট ফাইলগুলিকে লেক্সিকালি বাছাই করা দরকার।

আপনার শেলটি বাশ বা ksh বলে ধরে নেওয়া:

join -t $'\t' <(sort ids.csv) <(sort table.csv)

বাছাই করার প্রয়োজন ছাড়াই, স্বাভাবিক অজানা সমাধান

awk -F '\t' 'NR==FNR {id[$1]; next} $1 in id' ids.csv table.csv

আমি যেমন চেষ্টা করেছি কিন্তু শেষ পর্যন্ত জানাতে ব্যর্থ হলাম, যোগসূত্র হ'ল একটি ক্লডজ। আমার জন্য এত ভাল কাজ করে না।
আলমার

1
joinক্লোডজ নয়: আপনার শব্দগুলি আপনি এটি বের করতে পারতেন না। আপনার মন খুলুন এবং শিখুন। আপনি কী আউটপুট পেয়েছেন এবং কীভাবে তা আপনি প্রত্যাশা করেছেন তার থেকে আলাদা?
গ্লেন জ্যাকম্যান

+1, এটি একটি কাজ join
don_crissti

awkসমাধান এখানে খুব দ্রুত এবং আমার উদ্দেশ্যে দক্ষ (আমি ~ 100M লাইনের ফাইল থেকে কয়েকশ এর সাব-সেট নির্বাচন আহরণের করছি) হল
লুক

2

এই SO প্রশ্নের উত্তরগুলি আমাকে যোগদানের সাথে নিগলগুলি কাছাকাছি পেতে সহায়তা করেছিল। মূলত, আপনি যখন ফাইলটিকে যোগদানের জন্য প্রেরণের প্রস্তুতির অনুসারে বাছাই করেছেন, আপনার অবশ্যই নিশ্চিত হওয়া দরকার যে আপনি যে কলামে যোগদান করছেন তার উপর ভিত্তি করে আপনি বাছাই করছেন। সুতরাং এটি যদি প্রথমটি হয় তবে আপনাকে ফাইলের মধ্যে বিভাজক চরিত্রটি কী তা বলতে হবে এবং এটি প্রথম ক্ষেত্রের (এবং কেবলমাত্র প্রথম ক্ষেত্র) বাছাই করতে চান। অন্যথায় যদি প্রথম ক্ষেত্রের পরিবর্তনশীল প্রস্থ থাকে (উদাহরণস্বরূপ), আপনার বিভাজক এবং সম্ভবত অন্যান্য ক্ষেত্রগুলি বাছাই ক্রমের উপর প্রভাব ফেলতে পারে।

সুতরাং, আপনার পৃথক পৃথক চরিত্রটি নির্দিষ্ট করতে ধরণের -t বিকল্পটি ব্যবহার করুন এবং ক্ষেত্রটি নির্দিষ্ট করতে -k বিকল্পটি ব্যবহার করুন (মনে রাখবেন যে আপনার শুরু এবং শেষের ক্ষেত্রের প্রয়োজন - এটি একই রকম হলেও - বা এটি চরিত্রটি থেকে সাজবে) লাইনের শেষে)।

সুতরাং এই প্রশ্নের মতো একটি ট্যাব-বিযুক্ত ফাইলের জন্য, নিম্নলিখিতগুলির কাজ করা উচিত ( কাঠামোর জন্য গ্লেনের উত্তরের জন্য ধন্যবাদ ):

join -t$'\t' <(sort -d ids.csv) <(sort -d -t$'\t' -k1,1 table.csv) > output.csv

(রেফারেন্সের জন্য, -d পতাকাটির অর্থ অভিধানের বাছাই leading আপনি নেতৃস্থানীয় সাদা স্থান উপেক্ষা করার জন্য-বি পতাকাটি ব্যবহার করতে, দেখুন man sortও দেখতেও চাইতে পারেন man join)।

আরও সাধারণ উদাহরণ হিসাবে ধরুন, আপনি দুটি কমা-বিচ্ছিন্ন ফাইলগুলিতে যোগ দিচ্ছেন - input1.csvতৃতীয় কলামে এবং input2.csvচতুর্থ দিকে। আপনি ব্যবহার করতে পারেন

join -t, -1 3 -2 4 <(sort -d -t, -k3,3 input2.csv) <(sort -d -t, -k4,4 input2.csv) > output.csv

এখানে -1এবং -2অপশনগুলি নির্দিষ্ট করে যথাক্রমে প্রথম এবং দ্বিতীয় ইনপুট ফাইলগুলিতে কোন ক্ষেত্রগুলিতে যোগদান করতে হবে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.