GNU বাছাই স্থিতিশীল সাজান যখন সাজানোর ক্রম জানেন না


18

আমার একটি দ্বি-কলাম ফাইল আছে; ফাইলটি আমি এটি কলাম 1-তে ইতিমধ্যে সাজিয়েছি। আমি প্রতিটি কলাম 1 বিভাগের মধ্যে কলাম 2 বাছাই করতে চাই। তবে, sortকলাম 1 এর ক্রম ক্রম বুঝতে পারে না।

স্বাভাবিক উপায় (এখানে স্ট্যাকের অনুরূপ প্রশ্নগুলি থেকে) এটি হ'ল:

sort --stable -k1,1 -k2,2n

তবে আমি কে 1 এ বাছাই করতে পারি না, কারণ এটি স্বেচ্ছাসেবী।

উদাহরণ ইনপুট:

C 2
C 1
A 2
A 1
B 2 
B 1

এবং আউটপুট:

C 1
C 2
A 1
A 2
B 1 
B 2

উত্তর:


20

আপনি প্রতিটি ব্লকের জন্য একটি নতুন ধরণের শুরু করতে বিশ্রী ব্যবহার করতে পারেন:

% awk -v cmd="sort -k2,2" '$1 != prev {close(cmd); prev=$1} {print | cmd}' foo
C 1
C 2
A 1
A 2
B 1
B 2
  • $1 != prev {close(cmd); prev=$1} - যখন সংরক্ষিত মানটি আলাদা হয়, তখন আমাদের একটি নতুন ব্লক থাকে, তাই আমরা আগের কোনও শুরু বন্ধ করি sort
  • {print | "sort -k2,2"}'আউটপুটটি পাইপ করে sort, এটি ইতিমধ্যে চলমান না হলে এটি শুরু করে (অ্যাডাব্লিক কমান্ডগুলি এটি শুরু করে রাখতে পারে)

2
awk সত্যিই অবিশ্বাস্য। আমি যা প্রত্যাশা করছিলাম তার থেকেও এটি অনেক বেশি পছন্দ করে, যা ছিল একটি অজানা সাজসজ্জা-সাজানো-আনকোরেক্ট!
— ইভান বেন

আমি অন্য বনাম এর তুলনায় পারফেক্ট তুলনা করার চেষ্টা করেছি, কেন নিশ্চিত না যে এটি কেন আরও সংস্থান ব্যবহার করে ... কোন ধারণা? gist.github.com/EvanTheB/5b64eafb84eeaf51c289295ac06e1b0b
— ইভান বেন

আপনি কত রান জুড়ে গড়ে?
— মুরু

আমি কোনও গড়পড়তা করিনি, তবে পুনরাবৃত্তি এবং তদন্ত করার সময় ধারাবাহিক রানটাইমগুলি দেখছি।
— ইভান বেন

আপনি যদি তদন্ত করতে চান তবে আমি যা ব্যবহার করছি তার অনুরূপ ফাইলটি এখানে:seq 30 | xargs -L1 bash -cs 'yes $1 | head -1000000 | paste - <(seq 1000000) | shuf' bash
— ইভান বেন

12

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

awk '{print ($1 in a? c+0: ++c)"\t" $0; a[$1]}' file | sort -k1,1n  -k3,3 | cut -f 2-

আমি অবাক, কিন্তু আপনি সঠিক, এটি অন্য উত্তরের চেয়ে দ্রুত ছিল! আমার 100 মিলিয়ন লাইন ফাইলে 3 মিনিট বনাম 2 মিনিট (un 30 ইউনিক প্রথম কলাম)।
— ইভান বেন

1
প্রথম কলাম থেকে অনন্য কীটির অ্যারে রাখার দরকার নেই। আমি মনে করি বর্তমান লাইনের প্রথম কলামটি আগেরটির সাথে তুলনা করার পক্ষে যথেষ্ট হওয়া উচিত।
— কুসালানন্দ

এর মতো কিছু awk -v OFS="\t" '$1 != prev { key++ } { print key, $0; prev = $1 }(অরক্ষিত)।
— Kusalananda
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.