অন্য কোনও ফাইলে পাওয়া লাইনের উপর নির্ভর করে কোনও ফাইল থেকে লাইনগুলি সরান


11

File1.txt ফাইলের মতো লাইন রয়েছে:

/api/purchase/<hash>/index.html

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

/api/purchase/12ab09f46/index.html

ফাইল file2.csv এর মতো লাইন রয়েছে:

<hash>,timestamp,ip_address

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

12ab09f46,20150812235200,22.231.113.64 
a77b3ff22,20150812235959,194.66.82.11

আমি ফাইল 2.এসএসভি ফিল্টার করতে চাই যেখানে সমস্ত লাইন যেখানে হ্যাশের ফাইলটি ফাইল 1.txt তে উপস্থিত রয়েছে সেগুলি সরিয়ে ফেলতে চাই। এটি বলার জন্য:

cat file1.txt | extract <hash> | sed '/<hash>/d' file2.csv

বা এই জাতীয় কিছু।

এটি সোজা হওয়া উচিত, তবে আমি এটি কার্যকর করতে অক্ষম বলে মনে করি।

কেউ কি এই কাজের জন্য একটি কাজের পাইপলাইন সরবরাহ করতে পারেন?

উত্তর:


13

cut -d / -f 4 file1.txt | paste -sd '|' | xargs -I{} grep -v -E {} file2.csv

ব্যাখ্যা:

cut -d / -f 4 file1.txt প্রথম ফাইলটি থেকে হ্যাশগুলি নির্বাচন করবে

paste -sd '|' সমস্ত হ্যাশগুলিতে একটি নিয়মিত প্রকাশের সাথে যোগ দেবে। H1|H2|H3

xargs -I{} grep -v -E {} file2.csvযুক্তি হিসাবে পূর্ববর্তী প্যাটার্নটির সাথে গ্রেপকে আহ্বান জানাবে, xargs {}এর বিষয়বস্তুর সাথে প্রতিস্থাপন করবেSTDIN

আপনার যদি না থাকে তবে pasteআপনি এটির সাথে প্রতিস্থাপন করতে পারেনtr "\\n" "|" | sed 's/|$//'


3
+1 টি কিন্তু জন্য কোন প্রয়োজন catশুধু cut -d / -f 4 file1.txt। বা আপনি যদি অনুক্রমিক চেহারা পছন্দ করেন,<file1.txt cut -d / -f 4
স্পারহক

@ স্পারহাক ধন্যবাদ! আমি জানতাম না ;-) সমাধান আপডেট হয়েছে :-)
গ্যাব্রিয়েল লানা

11

সম্ভাব্য awkসমাধান:

awk 'NR == FNR { x[$4] = 1; next; } { if (!($1 in x)) print $0; }' FS="/" file1.txt FS="," file2.txt

প্রথমে আমরা (ফিল্ড বিভাজক) "/" file1.txtব্যবহার করে পড়ি FSএবং ক্ষেত্র থেকে কীগুলির মানগুলির সাথে অ্যারে এক্স তৈরি করব $4যা আপনি চান হ্যাশ। পরবর্তী আমরা দ্বিতীয় ফাইলটি পড়ার file2.txtসেটিং FSহতে ,এবং চেক যদি ক্ষেত্রের মান $1অ্যারের মধ্যে কী-এর মত কোন অস্তিত্ব নেই xএবং এটি আমরা এটা মুদ্রণ না পারেন।
মন্তব্যে প্রস্তাবিত একই আরও মুশকিল হতে পারে:

awk 'NR == FNR { x[$4] = 1; next; } !($1 in x)' FS="/" file1.txt FS="," file2.txt

আমি আপনার প্রচেষ্টার প্রশংসা করি, তবে আমি ভয় করি যে এটি আমার মাথার উপরে উঠে যায়। আমি আশা করি কিছু সমাধান / গ্রেপ / বিড়াল মিশ্রণের উপর ভিত্তি করে একটি সমাধান সম্ভব হবে।
মার্কো ফাউস্টিনেল্লি

1
আমি একটি ব্যাখ্যা যুক্ত করব, এটি সহজ। এবং হতে পারে যে কেউ আপনার পছন্দসই সরঞ্জামগুলির সাথে সমাধানের প্রস্তাব দেবেন।
ট্যালিজিন

কেন কেবল !($1 in x)তার পরিবর্তে নয়{ if (!($1 in x)) print $0; }
ইরুভর

@ 1_CR এটি আমার খারাপ অভ্যাস, আমি জানি এটি আরও বোকামিযুক্ত হতে পারে তবে আমি সবসময়ই মনে করি এটি ওপিকে ব্যাখ্যা করার জন্য সহজ হবে।
ট্যালিজিন

@ মুজিওতো এখনও, আমি মনে করি যে এই awkভিত্তিক সমাধান হিসাবে অন্যান্য সরঞ্জামগুলি শিখতে শুরু করার কোনও ক্ষতি নেই ... দীর্ঘমেয়াদে, আপনি সরলতার জন্য কম পাইপ ব্যবহার করে যে সমাধানগুলি অর্জন করতে পারেন তার সমাধানের দিকে গুরুতর হওয়া শিখবেন ... :)
hjk

5

জন্য গনুহ sed

sed -z 's%.*/\([^/]*\)/index.html\n%\1\\|%g;s%^%/%;s%\\|$%/d%' file1.csv |
sed -f - file2.csv

যেখানে প্রথম sed মত sed-কমান্ড-বিন্যাসে হ্যাশ উৎপন্ন দ্রব্য তালিকা /12ab09f46\|a77b3ff22\|..../dএবং স্থানান্তর পরবর্তী কিন্তু -script যা ইনপুট তাই থেকে কমান্ড উপরে সার্চ -f -বিকল্প।
সঙ্গে একই , grep

grep -oP '[^/]*(?=/index.html$)' file1.csv | grep -Fvf - file2.csv

বা পার্ল-এক্সপ্রেশন ছাড়াই:

grep -o '[^/]*/index.html$' file1.csv | 
grep -o '^[^/]*' | 
grep -Fvf - file2.csv

বা কাটা আরও ভাল :

cut -d/ -f4 file1.csv | grep -Fvf - file2.csv

আমি যা খুঁজছিলাম তা এটি আমাকে দেখায়। আপনি কিছুটা বর্ণনা করতে পারেন? দ্বিতীয় কমান্ড ফাইল2.csv থেকে লাইনগুলি সরিয়ে ফেলবে তা আমি দেখতে পাচ্ছি না।
মার্কো ফাউস্টিনেলি

@ মুজিওতো আপডেট দেখুন
কস্টাস

2
#!/bin/bash
cut -d, -f1 file2 | while read key ; do 
   #check for appearance in file1 with successful grep:
   #exit status is 0 if pattern is found, only search for at least 1
   #appearance -> to speed it up
   if [[ $(grep -m 1 "/$key/" file1) ]] ; then
      sed "/^$key,/d" -i file2
      #note that we are gradually overwriting file2 (-i option),
      #so make a backup!
   fi
done

জেনে রাখুন যে অনুসন্ধানের কাঁটা ফোটা হয় /$key/এবং ^$key,কমাতে ফলাফল পারেন মধ্যে দুই স্ল্যাশ (ফাইল 1) হতে বা লাইনের প্রথম এন্ট্রি এবং একটি কমা (ফাইল 2) দ্বারা অনুসরণ করা হয়। কীগুলি দেখতে দেখতে এটি নিরাপদ করা উচিত

a,values
a1,values

ফাইল 2 বা মত

/api/../a1/../
/api/../a/../

ফাইল 1 এ


2

আমি কেবল নিম্নলিখিত একটি লাইনারটি চেষ্টা করেছি এবং মনে হচ্ছে এটি কাজটি করছে:

 for i in `cat file1.txt  | awk -F"/" '{print $4}'`; do echo "\n $i" ; sed -ri "/^$i,/d" file2.csv ; done

দয়া করে প্রথমে প্রতিস্থাপন -ri সঙ্গে -re এটা পরীক্ষা করা হবে। - এটি একটি শুকনো রান চালায়, এবং যদি সবকিছু ঠিক থাকে তবে আপনি এটি -ri দিয়ে চালাতে পারেন


মিমিএমএইচ, আমি আপনার কোডের আউটপুটটিকে একটি অস্থায়ী ফাইলে পুনঃনির্দেশ করেছি এবং এতে প্রায় 30k লাইন রয়েছে, যেখানে file2.csv প্রাথমিকভাবে 240 হয়েছে এবং এটি ফিল্টার হওয়ার কথা।
মার্কো ফাউস্টিনেল্লি

ঠিক আছে, আমি মনে করি কারণ এটি আমি প্রতি ফাইলটি প্রথম ফাইলটিতে মুদ্রণ করি, যখন আমি প্রতিস্থাপন করি (প্রতিধ্বনি "\ n" $ i অংশ)। যাইহোক আপনি যদি এটি -ri দিয়ে চালান তবে আপনাকে পুনর্নির্দেশ করতে হবে না, কারণ এটি জায়গায় প্রতিস্থাপন করে
প্রাইমো

এছাড়াও যদি আপনি -re দিয়ে চালিত হন এবং পুনর্নির্দেশ করেন তবে আপনার প্রথম ফাইলটিতে যতগুলি হ্যাশ রয়েছে তার জন্য ফাইল 2 পুনরাবৃত্তি হবে। মূলত প্রথম ফাইলের প্রতিটি হ্যাশের জন্য এটি এটি দ্বিতীয় ফাইলে প্রতিস্থাপন করে এবং ফলাফলটি মুদ্রণ করে, সুতরাং আপনার এত লাইন রয়েছে।
প্রাইমো

1

গ্যাব্রিয়েল লানার উত্তর ছাড়াও দয়া করে নোট করুন যে স্ট্যান্ডার্ড ইনপুট থেকে সামগ্রী পড়তে বিএসডি পেস্ট কমান্ডের ড্যাশ নির্দিষ্ট করা দরকার।

পেস্ট কমান্ড ম্যানুয়াল

যদি '-' এক বা একাধিক ইনপুট ফাইলের জন্য নির্দিষ্ট করা থাকে, তবে স্ট্যান্ডার্ড ইনপুট ব্যবহৃত হয়; স্ট্যান্ডার্ড ইনপুট '-' এর প্রতিটি উদাহরণের জন্য বৃত্তাকারে একবারে একটি লাইন পড়ে থাকে instance

সুতরাং চূড়ান্ত নীচের মত পরিবর্তন করা প্রয়োজন

cut -d / -f 4 file1.txt | paste -sd '|' - | xargs -I{} grep -v -E {} file2.csv
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.