ফাঁকা স্থান সহ লাইনের দৈর্ঘ্য অনুসারে একটি পাঠ্য ফাইল বাছাই করুন


137

আমার কাছে এমন একটি সিএসভি ফাইল রয়েছে যা দেখতে এমন দেখাচ্ছে

এএস 2345, এএসডিএফ 1232, মিঃ সমতল উদাহরণ, 110 বাইনারি অ্যাভ। আটলান্টিস, আরআই, 12345, (999) 123-5555,1.56
এএস 2345, এএসডিএফ 1232, মিসেস সাদামাটা উদাহরণ, 1121110 টার্নারি স্ট। 110 বাইনারি এভ .., আটলান্টিস, আরআই, 12345, (999) 123-5555,1.56
এএস 2345, এএসডিএফ 1232, মিঃ সমতল উদাহরণ, 110 বাইনারি অ্যাভ। লিবার্টি সিটি, আরআই, 12345, (999) 123-5555,1.56
এএস 2345, এএসডিএফ 1232, মিঃ প্লেইন উদাহরণ, 110 টার্নারি অ্যাভে।, কিছু শহর, আরআই, 12345, (999) 123-5555,1.56

ফাঁকাসহ লাইনের দৈর্ঘ্য অনুসারে আমার এটি বাছাই করা দরকার। নিম্নলিখিত কমান্ডটিতে ফাঁকা স্থান অন্তর্ভুক্ত নেই, এটি কীভাবে পরিবর্তন করার কোনও উপায় আছে যাতে এটি আমার পক্ষে কার্যকর হবে?

cat $@ | awk '{ print length, $0 }' | sort -n | awk '{$1=""; print $0}'

21
আমি সত্যিই বাইনারি এভিনিউ বা তিন রাস্তার বাস করতে, যাদের অবশ্যই ভালো জিনিস সাথে একমত হবে চাই "8192 হয় একটি রাউন্ড নম্বর"
schnaader

উত্তর:


224

উত্তর

cat testfile | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2-

অথবা, কোনও সম-দৈর্ঘ্যের লাইনের আপনার মূল (সম্ভবত অনিচ্ছাকৃত) সাব-বাছাই করতে:

cat testfile | awk '{ print length, $0 }' | sort -n | cut -d" " -f2-

উভয় ক্ষেত্রেই, আমরা আপনার চূড়ান্ত কাটার জন্য ওড়না থেকে দূরে সরিয়ে আপনার বিবৃত সমস্যাটি সমাধান করেছি।

মিলের দৈর্ঘ্যের লাইন - টাইয়ের ক্ষেত্রে কী করতে হবে:

মিলের দৈর্ঘ্যের লাইনের জন্য আরও বাছাইয়ের প্রয়োজন ছিল কিনা তা প্রশ্নটি নির্দিষ্ট করে নি। আমি ধরে নিয়েছি যে এটি অনাকাঙ্ক্ষিত এবং একে অপরের বিরুদ্ধে এই ধরণের লাইনগুলি বাছাই করা রোধ করতে -s( --stable) ব্যবহারের পরামর্শ দিয়েছিল এবং সেগুলি ইনপুটতে যেভাবে প্রাসঙ্গিক হয় তা সেগুলি রেখে দেয়।

(যারা এই সম্পর্কগুলিকে বাছাই করতে আরও নিয়ন্ত্রণ চান তারা হয়ত বাছাইয়ের --keyবিকল্পটি দেখতে পারেন ))

কেন প্রশ্নটির চেষ্টা করা সমাধান ব্যর্থ হয় (অ্যাঙ্ক লাইন-পুনর্নির্মাণ):

এর মধ্যে পার্থক্যটি লক্ষ করা আকর্ষণীয়:

echo "hello   awk   world" | awk '{print}'
echo "hello   awk   world" | awk '{$1="hello"; print}'

তারা যথাক্রমে ফলন

hello   awk   world
hello awk world

প্রাসঙ্গিক ধারা (হাবা এর) ম্যানুয়াল শুধুমাত্র একটি সরাইয়া হিসাবে উল্লেখ করেছেন যে awk যখন আপনি একটি ক্ষেত্র পরিবর্তন (বিভাজক উপর ভিত্তি করে, ইত্যাদি) $ 0 পুরো পুনর্নির্মাণের যাচ্ছে। আমার ধারণা এটি পাগল আচরণ নয়। এটিতে এটি রয়েছে:

"অবশেষে, এমন সময়গুলি আসে যখন ক্ষেত্রগুলির বর্তমান মান এবং অফস ব্যবহার করে পুরো রেকর্ডটি পুনর্নির্মাণের জন্য জোর করে জোর করা সুবিধাজনক this

 $1 = $1   # force record to be reconstituted
 print $0  # or whatever else with $0

"এটি রেকর্ডটি পুনর্নির্মাণে বিশ্রী জোর করে" "

সমান দৈর্ঘ্যের কিছু লাইন সহ পরীক্ষার ইনপুট:

aa A line   with     MORE    spaces
bb The very longest line in the file
ccb
9   dd equal len.  Orig pos = 1
500 dd equal len.  Orig pos = 2
ccz
cca
ee A line with  some       spaces
1   dd equal len.  Orig pos = 3
ff
5   dd equal len.  Orig pos = 4
g

1
হিমাইল, হ্যাঁ, ধন্যবাদ আমি তার ও আমার মধ্যে গুরুত্বপূর্ণ পার্থক্যগুলিতে মনোনিবেশ করতে সক্ষম করার জন্য যেখানে সম্ভব সেখানে ওপি'র চেষ্টা করা সমাধানের আকারটি মেলানোর চেষ্টা করেছি।
নীলব

1
cat $@এটিও ভাঙা out আপনি একেবারে অবশ্যই এটিকে উদ্ধৃত করতে চান, যেমনcat "$@"
ট্রিপলি

27

Neillb থেকে awk সমাধান মহান আপনি কি সত্যিই ব্যবহার করতে চান তাহলে হয় awkএবং এটি ব্যাখ্যা দিয়েছে কেন এটি একটি ঝগড়া আছে, কিন্তু যদি আপনি যা চান তা দ্রুত কাজ সম্পন্ন হয় এবং পরোয়া করি না আপনি এটি না, এক সমাধান ব্যবহার করা sort()ইনপুট লাইনগুলিতে পুনরাবৃত্তি করতে কাস্টম তুলনা রুটিন সহ পার্লের ক্রিয়া। এখানে একটি ওলাইনার রয়েছে:

perl -e 'print sort { length($a) <=> length($b) } <>'

আপনি এটি আপনার পাইপলাইনে যেখানেই প্রয়োজন যেখানে এটি লাগাতে পারেন, হয় STDIN ( catবা শেল পুনর্নির্দেশ থেকে) গ্রহণ করুন বা কেবল অন্য যুক্তি হিসাবে ফাইলের নামটি পার্লকে দিন এবং এটি ফাইলটি খুলতে দিন।

আমার ক্ষেত্রে আমি তাই আমি কোন মতেই বার দীর্ঘতম লাইন প্রথম, প্রয়োজন $aএবং $bতুলনায়।


এটি আরও ভাল সমাধান কারণ ইনপুট ফাইলে সংখ্যাসূচক এবং বর্ণানুক্রমিক লাইন থাকা অবস্থায় অজানা অপ্রত্যাশিতভাবে বাছাইয়ের কারণ হয়ে থাকে এখানে অন লাইন কমান্ড: $ বিড়াল টেস্টফিল | perl -e 'মুদ্রণ সাজান {দৈর্ঘ্য ($ a) <=> দৈর্ঘ্য ($ বি)} <>'
আলেমল

দ্রুত! <1 সেকেন্ডে 465,000 লাইন ফাইল (প্রতি লাইনে একটি শব্দ) আউটপুট অন্য ফাইলে পুনর্নির্দেশ করা হয়েছিল - সুতরাং:cat testfile.txt | perl -e 'print sort { length($a) <=> length($b) } <>' > out.txt
সিএসফাস

স্ট্রবেরি type testfile.txt | perl -e "print sort { length($a) <=> length($b) } <>" > out.txt
পার্ল

14

পরিবর্তে এই আদেশ ব্যবহার করে দেখুন:

awk '{print length, $0}' your-file | sort -n | cut -d " " -f2-

10

বেঞ্চমার্ক ফলাফল

নীচে এই প্রশ্নের অন্যান্য উত্তর থেকে সমাধান জুড়ে একটি মানদণ্ডের ফলাফল রয়েছে।

পরীক্ষা পদ্ধতি

  • 10 ক্রমিক একটি দ্রুত মেশিনে রান করে, গড়ে গড়ে
  • পার্ল 5.24
  • অদম্য ৩.১.৫ (4.1.0 বার গাব 2% দ্রুত ছিল)
  • ইনপুট ফাইলটি 550MB, 6 মিলিয়ন লাইন মনস্ট্রোসিটি (ব্রিটিশ ন্যাশনাল কর্পাস txt)

ফলাফল

  1. কালেবের perlসমাধানটি 11.2 সেকেন্ড সময় নিয়েছিল
  2. আমার perlসমাধান 11.6 সেকেন্ড সময় নিয়েছে
  3. নীলব এর awkসমাধান # 1 20 সেকেন্ড সময় নিয়েছে
  4. neillb এর awkসমাধান # 2 23 সেকেন্ড সময় নিয়েছে
  5. অনুভার awkসমাধান ২৪ সেকেন্ড সময় নিয়েছিল
  6. জোনাথনের awkসমাধানটি 25 সেকেন্ড সময় নিয়েছিল
  7. ফ্রেটজের bashসমাধানগুলি দ্রবণগুলির চেয়ে 400x বেশি সময় নেয় awk(100000 লাইনের কাটা পরীক্ষার কেস ব্যবহার করে)। এটি ঠিক কাজ করে, চিরকাল লাগে forever

অতিরিক্ত perlবিকল্প

এছাড়াও, আমি আরও একটি পার্ল সমাধান যুক্ত করেছি:

perl -ne 'push @a, $_; END{ print sort { length $a <=> length $b } @a }' file

6

খাঁটি বাশ:

declare -a sorted

while read line; do
  if [ -z "${sorted[${#line}]}" ] ; then          # does line length already exist?
    sorted[${#line}]="$line"                      # element for new length
  else
    sorted[${#line}]="${sorted[${#line}]}\n$line" # append to lines with equal length
  fi
done < data.csv

for key in ${!sorted[*]}; do                      # iterate over existing indices
  echo -e "${sorted[$key]}"                       # echo lines with equal length
done

3

length()ফাংশন শূণ্যস্থান অন্তর্ভুক্ত আছে। আমি আপনার পাইপলাইনে ( UUOC এড়ানো সহ ) কেবলমাত্র সামান্য সামঞ্জস্য করব ।

awk '{ printf "%d:%s\n", length($0), $0;}' "$@" | sort -n | sed 's/^[0-9]*://'

sedকমান্ড সরাসরি সংখ্যা এবং কোলন দ্বারা যোগ সরিয়ে ফেলা হবে awkকমান্ড। বিকল্পভাবে, আপনার ফর্ম্যাটিং থেকে awk:

awk '{ print length($0), $0;}' "$@" | sort -n | sed 's/^[0-9]* //'

2

আমি খুঁজে পেয়েছি যে এই ফাইলগুলি যদি কোনও সংখ্যার সাথে শুরু হওয়া লাইনগুলি অন্তর্ভুক্ত করে তবে সেগুলি কার্যকর হবে না, কারণ সমস্ত গণনা করা লাইনগুলির সাথে সেগুলি সংখ্যায় বাছাই করা হবে। সমাধান দিতে হয় (সাধারণ-সাংখ্যিক-সাজানোর) পরিবর্তে পতাকা (সাংখ্যিক-সাজানোর):sort-g-n

awk '{ print length, $0 }' lines.txt | sort -g | cut -d" " -f2-

2
হাই, মার্কাস লাইন দৈর্ঘ্যের বিপরীতে - লাইন দৈর্ঘ্যের সাথে লাইনের ক্ষেত্রে বাদে বাছাইয়ের কোনও প্রভাব আছে হিসাবে - আমি লাইন সামগ্রী (সংখ্যা বা না) পর্যবেক্ষণ করি না। এই আপনি কি বোঝাতে চেয়েছিলেন? এই ধরনের ক্ষেত্রে, আমি কোনও উন্নতি পাওয়ার -nপ্রস্তাবিত -gথেকে আপনার কাছে সাজানোর পদ্ধতিগুলি সন্ধান করি নি, তাই আমি প্রত্যাশা করি না। আমি এখন আমার উত্তরে সম্বোধন করেছি, কীভাবে সম-দৈর্ঘ্য রেখাগুলির উপ-বাছাই নিষিদ্ধ করবেন (ব্যবহার করে --stable)। আপনি যা বোঝাতে চেয়েছিলেন সেটাই ছিল বা না, এটি আমার নজরে আনার জন্য ধন্যবাদ! আমি এটি পরীক্ষা করার জন্য একটি বিবেচিত ইনপুট যুক্ত করেছি।
নিলব

4
না, আমি এটিকে ভেঙে দিয়ে ব্যাখ্যা করব। কেবল awkঅংশটি লাইনের দৈর্ঘ্য এবং একটি স্থানের সাথে উপরিযুক্ত লাইনের একটি তালিকা তৈরি করবে। এটিতে পাইপ দেওয়া sort -nপ্রত্যাশার মতো কাজ করবে। তবে এই লাইনের যে কোনওটির শুরুতে ইতিমধ্যে একটি সংখ্যা থাকলে সেই লাইনগুলি দৈর্ঘ্য + স্পেস + সংখ্যা দিয়ে শুরু হবে। sort -nসেই স্থানটিকে অগ্রাহ্য করে এবং এটি দৈর্ঘ্য + সংখ্যা থেকে সংযুক্ত এক নম্বর হিসাবে বিবেচনা করবে। ব্যবহার -gপতাকা পরিবর্তে প্রথম স্থান থামবে, একটি সঠিক সাজানোর ফলনশীল হবে। কয়েকটি সংখ্যা-উপসর্গযুক্ত লাইন সহ একটি ফাইল তৈরি করে নিজে চেষ্টা করুন এবং কমান্ডটি ধাপে ধাপে চালাবেন।
মার্কাস অমলথিয়া ম্যাগনসন

1
আমি এটিও দেখতে পেয়েছি যে sort -nস্থানটিকে অবজ্ঞা করে এবং একটি ভুল বাছাই করে। sort -gসঠিক ক্রম আউটপুট।
রবার্ট স্মিথ

আমি বর্ণনা ইস্যু পুনর্গঠন করতে পারবে না -nsort (GNU coreutils) 8.21infoডকুমেন্টেশন বর্ণনা -gকম দক্ষ এবং সম্ভাব্য কম সুনির্দিষ্ট (এটা ভাসে সংখ্যার পরিবর্তন করে) হিসাবে, তাই সম্ভবত এটি ব্যবহার করবেন না যদি আপনি প্রয়োজন হবে না।
ফিলস

এনবি ডকুমেন্টেশন এর জন্য -n: "সংখ্যাসমূহ অনুসারে বাছাই করুন number সংখ্যাটি প্রতিটি লাইন শুরু হয় এবং blanচ্ছিক ফাঁকা, একটি'চ্ছিক '-' চিহ্ন এবং শূন্য বা আরও বেশি সংখ্যা সম্ভবত হাজার বিভাজক দ্বারা পৃথক করা হয়, optionচ্ছিকভাবে দশমিক-বিন্দুর অক্ষর এবং শূন্য বা আরও বেশি সংখ্যার দ্বারা পৃথক হয় "একটি ফাঁকা নম্বর '0' হিসাবে গণ্য করা হয়। 'এলসি_নুমারিক' লোকেল দশমিক-পয়েন্টের অক্ষর এবং হাজার হাজার বিভাজক নির্দিষ্ট করে default ডিফল্টরূপে একটি ফাঁকা স্থান বা একটি ট্যাব, তবে 'এলসি_সিটিওয়াইপি' লোকেল এটিকে পরিবর্তন করতে পারে।"
ফিলস


2

1) খাঁটি বিশ্রী সমাধান। ধরা যাক সেই লাইনের দৈর্ঘ্য তখন আর বেশি> 1024 নাও হতে পারে

বিড়াল ফাইলের নাম | awk 'BEGIN {min = 1024; s = "";} {l = দৈর্ঘ্য ($ 0); যদি (l <মিনিট) {মিনিট = l; s = $ 0;}} END {মুদ্রণ s} '

২) সব লাইনের মাত্র ১ টি শব্দ ধরে নেওয়া একটি লাইনার বাশ সমাধান, তবে যে কোনও ক্ষেত্রেই সমস্ত লাইনের শব্দের সংখ্যা একই থাকে:

লাইন = $ (বিড়াল ফাইলের নাম); for লাইনে k এর জন্য; do printf "" k "; প্রতিধ্বনি $ কে | wc -L; সম্পন্ন | সাজানো-কে 2 | মাথা -n 1 | কাট-ডি "" -ফ 1


1

দৈর্ঘ্য অনুসারে লাইনগুলি বাছাই করার জন্য এখানে একটি মাল্টিবাইট-সামঞ্জস্যপূর্ণ পদ্ধতি। এটি প্রয়োজন:

  1. wc -m আপনার কাছে উপলব্ধ (ম্যাকোস এটি রয়েছে)।
  2. আপনার বর্তমান লোকেল সেটিংস এর দ্বারা, মাল্টি বাইট অক্ষর, যেমন সমর্থন LC_ALL=UTF-8। আপনি এটি আপনার .bash_profile এ সেট করতে পারেন বা কেবল নীচের কমান্ডের আগে এটি প্রিনড করে।
  3. testfile আপনার লোকেলের সাথে মিলে একটি অক্ষর এনকোডিং রয়েছে (যেমন, ইউটিএফ -8)।

এখানে সম্পূর্ণ আদেশ:

cat testfile | awk '{l=$0; gsub(/\047/, "\047\"\047\"\047", l); cmd=sprintf("echo \047%s\047 | wc -m", l); cmd | getline c; close(cmd); sub(/ */, "", c); { print c, $0 }}' | sort -ns | cut -d" " -f2-

খণ্ড খণ্ডের ব্যাখ্যা:

  • l=$0; gsub(/\047/, "\047\"\047\"\047", l);Aw প্রতিটি লাইনের অনুলিপি পরিবর্তনশীল একটি অনুলিপি তৈরি করে lএবং ডাবল-পলায়ন করে 'যাতে লাইনটি নিরাপদে শেল কমান্ড হিসাবে প্রতিধ্বনিত হয় ( \047অষ্টাল স্বরলিপিতে একক উদ্ধৃতি)।
  • cmd=sprintf("echo \047%s\047 | wc -m", l);← এটি হ'ল আদেশটি যা আমরা কার্যকর করব, যা পালানো রেখার প্রতিধ্বনি করে wc -m
  • cmd | getline c;← কমান্ড কপি অক্ষর সংখ্যা মান awk পরিবর্তনশীল মধ্যে ফিরিয়ে দেওয়া হয় executes c
  • close(cmd); One এক প্রক্রিয়াতে খোলা ফাইলের সংখ্যার উপর সিস্টেমের সীমাটি আঘাত করা এড়াতে শেল কমান্ডে পাইপটি বন্ধ করুন।
  • sub(/ */, "", c);Returned দ্বারা প্রদত্ত অক্ষর গণনা মান থেকে সাদা স্থান ছাঁটাই করে wc
  • { print c, $0 } । রেখার অক্ষর গণনা মান, একটি স্থান এবং মূল লাইনটি মুদ্রণ করে।
  • | sort -nsThe লাইনগুলি (প্রেন্টেড অক্ষর গণনা মান অনুসারে) সংখ্যাগতভাবে ( -n) এবং স্থিতিশীল সাজানোর ক্রম বজায় রাখে ( -s)।
  • | cut -d" " -f2- The চাপানো অক্ষর গণনা মানগুলি সরায়।

এটি ধীর গতিতে (দ্রুত ম্যাকবুক প্রোতে সেকেন্ডে কেবল 160 লাইন) কারণ এটি প্রতিটি লাইনের জন্য একটি সাব-কমান্ড কার্যকর করতে পারে।

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

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