ইউনিক্স কমান্ড লাইনের কোনও ফাইল থেকে এলোমেলো লাইন পড়ার সহজ উপায় কী?


263

ইউনিক্স কমান্ড লাইনের কোনও ফাইল থেকে এলোমেলো লাইন পড়ার সহজ উপায় কী?


প্রতিটি লাইন একটি নির্দিষ্ট দৈর্ঘ্য প্যাড করা হয়?
ট্র্যাকার 1

না, প্রতিটি লাইনের অক্ষরগুলির পরিবর্তনশীল সংখ্যা রয়েছে

উত্তর:


383

আপনি ব্যবহার করতে পারেন shuf:

shuf -n 1 $FILE

একটি ইউটিলিটিও বলা হয় rl। ডেবিয়ান এ এটি randomize-linesপ্যাকেজে রয়েছে যা আপনি যা চান ঠিক তেমন করে, যদিও সমস্ত ডিস্ট্রোজে পাওয়া যায় না। এর হোম পৃষ্ঠায় এটি shufপরিবর্তে ব্যবহারের প্রস্তাব দেয় (এটি তৈরি করার সময় উপস্থিত ছিল না, আমি বিশ্বাস করি)। shufজিএনইউ কোর্টিলস এর অংশ, rlনা।

rl -c 1 $FILE

2
shufটিপ দেওয়ার জন্য ধন্যবাদ , এটি ফেডোরায় অন্তর্নির্মিত।
চেং

5
Andalso, sort -Rস্পষ্টভাবে এক অপেক্ষা করতে যাচ্ছে অনেক 80kk লাইন - -, যেহেতু, যদি যথেষ্ট বিশাল ফাইল সঙ্গে তার আচরণ shuf -nকাজ করে বেশ তাত্ক্ষণিকভাবে।
রুবেন্স

23
আপনি coreutilsহোমব্রিউ থেকে ইনস্টল করে ওএস এক্স-এ শিফ পেতে পারেন । gshufপরিবর্তে ডাকা হতে পারে shuf
অ্যালিসা রস

2
একইভাবে, আপনি randomize-linesওএস এক্স এর মাধ্যমে ব্যবহার করতে পারেনbrew install randomize-lines; rl -c 1 $FILE
জ্যামি

4
মনে রাখবেন যে shufএটি জিএনইউ কোরিউটিলের অংশ এবং সুতরাং অগত্যা * বিএসডি সিস্টেমে (বা ম্যাক?) উপলব্ধ হবে না (ডিফল্টরূপে)। নীচে @ ট্র্যাকার 1 এর পার্ল ওয়ান-লাইনারটি আরও বহনযোগ্য (এবং আমার পরীক্ষাগুলি দ্বারা, কিছুটা দ্রুত)।
অ্যাডাম কাটজ

74

অন্য বিকল্প:

head -$((${RANDOM} % `wc -l < file` + 1)) file | tail -1

28
{ND র্যান্ডম} কেবল 32768 এর চেয়ে কম সংখ্যা উত্পন্ন করে, তাই এটি বড় ফাইলগুলির জন্য ব্যবহার করবেন না (উদাহরণস্বরূপ ইংরেজি অভিধান)।
রাল্ফ

3
এটি আপনাকে প্রতিটি লাইনের যথাযথ একই সম্ভাবনা দেয় না, মডিউল অপারেশনের কারণে। ফাইলের দৈর্ঘ্য << 32768 (এবং এটি যদি এই সংখ্যাটি ভাগ করে দেয় তবে মোটেও তা নয়) তবে এটি সবেমাত্র গুরুত্বপূর্ণ।
এনাফরি

10
আপনি এটি ব্যবহার করে 30-বিট এলোমেলো সংখ্যায় প্রসারিত করতে পারেন (${RANDOM} << 15) + ${RANDOM}। এটি লক্ষণীয়ভাবে হ্রাস করে এবং এটি 1 বিলিয়ন লাইন থাকা ফাইলগুলির জন্য কাজ করতে দেয়।
নিওনেও

@nneonneo: খুব, কৌতুক ঠান্ডা যদিও এই লিঙ্কে অনুযায়ী এটা $ {র্যান্ডম} OR'ing হবে 'PLUS'ing পরিবর্তে গুলি stackoverflow.com/a/19602060/293064
জে টেলর

+এবং |একই যেহেতু ${RANDOM}0..32767 সংজ্ঞা দ্বারা হয়।
nneonneo

70
sort --random-sort $FILE | head -n 1

(আমি উপরে শূফ পদ্ধতির তুলনায় আরও ভাল পছন্দ করি - এমনকি আমি জানতাম না যে এর অস্তিত্ব আছে এবং আমি নিজেই সেই সরঞ্জামটি পাইনি)


10
+1 আমি এটি পছন্দ করি তবে আপনার খুব সাম্প্রতিক প্রয়োজন হতে পারে sortআমার কোনও সিস্টেমে কাজ করেনি (সেন্টস 5.5, ম্যাক ওএস 10.7.2)। এছাড়াও, বিড়ালের অকেজো ব্যবহার, এটিকে হ্রাস করা যেতে পারেsort --random-sort < $FILE | head -n 1
স্টিভ কেহলেট

sort -R <<< $'1\n1\n2' | head -11 এবং 2 ফেরত আসার সম্ভাবনা রয়েছে কারণ sort -Rডুপ্লিকেট লাইন একসাথে সাজানো হয়েছে। এটি একই ক্ষেত্রে প্রযোজ্য sort -Ruকারণ এটি সদৃশ লাইনগুলি সরিয়ে দেয়।
ল্রি

5
এটি তুলনামূলকভাবে ধীর, কারণ sortপাইপ দেওয়ার আগে পুরো ফাইলটি বদলানো দরকার headshufপরিবর্তে ফাইল থেকে এলোমেলো লাইনগুলি নির্বাচন করে এবং এটি আমার জন্য আরও দ্রুত।
বেংট

1
@ স্টিভ কেহলেট যখন আমরা সেখানে থাকি তখন sort --random-sort $FILE | headসবচেয়ে ভাল হবে, কারণ এটি সরাসরি ফাইলটি অ্যাক্সেস করার অনুমতি দেয়, সম্ভবত দক্ষ সমান্তরাল বাছাই সক্ষম করে
ওয়ায়েলজে

5
--random-sortএবং -Rঅপশন গনুহ সাজানোর নির্দিষ্ট হয় (তাই তারা বাসদ বা ম্যাক অপারেটিং সিস্টেম সাথে কাজ করবে না sort)। জিএনইউ বাছাই 2005 সালে এই পতাকাগুলি শিখেছে যাতে আপনার জিএনইউ কোর্টিলগুলি 6.0 বা আরও নতুন (যেমন সেন্টস 6) দরকার।
আরজেহান্টার

31

এটি সহজ।

cat file.txt | shuf -n 1

মঞ্জুর যে এটি "shuf -n 1 file.txt" এর থেকে নিজের চেয়ে ধীরে ধীরে কম ad


2
সর্বোত্তম উত্তর. আমি এই আদেশ সম্পর্কে জানতাম না। দ্রষ্টব্য যে -n 11 লাইন নির্দিষ্ট করে এবং আপনি এটি 1 টিরও বেশিতে পরিবর্তন করতে পারেন shufঅন্যান্য জিনিসের জন্যও ব্যবহার করা যেতে পারে; আমি কেবল পাইপ দিয়েছিলাম ps auxএবং এর grepসাথে এলোমেলোভাবে কোনও নামের সাথে মিলে যাওয়া প্রক্রিয়াগুলিকে এলোমেলোভাবে হত্যা করি।
sudo

18

perlfaq5: আমি কোনও ফাইল থেকে এলোমেলো লাইনটি কীভাবে নির্বাচন করব? উট বইয়ের একটি জলাধার-নমুনা সংক্রান্ত অ্যালগরিদম এখানে:

perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' file

পুরো ফাইলটি পড়ার ক্ষেত্রে স্পেসে এটির একটি উল্লেখযোগ্য সুবিধা রয়েছে Donald আপনি ডোনাল্ড ই নুথের আর্ট অফ কম্পিউটার প্রোগ্রামিং, খণ্ড 2, বিভাগ 3.4.2-এ এই পদ্ধতির একটি প্রমাণ পেতে পারেন।


1
কেবল অন্তর্ভুক্তির উদ্দেশ্যে (যদি উল্লেখ করা সাইটটি নিচে নেমে আসে), এখানে ট্র্যাকার 1 কোডটি নির্দেশ করেছেন: "বিড়ালের ফাইল নাম | পার্ল -e 'থাকাকালীন (<>) {পুশ (@ _, $ _);} মুদ্রণ @ : _ [RAND () * @: _]; ';'
অনিরওয়ান

3
এটি বিড়ালের অকেজো ব্যবহার। পারফাক্যাক 5 (এবং উটের বইয়ের সৌজন্যে) -এ কোডটি পাওয়া যায় যা এখানে সামান্য পরিবর্তিত: পার্ল-ই 'শ্রান্ড; র্যান্ড ($।) <1 && ($ লাইন = $ _) <> থাকাকালীন; মুদ্রণ $ লাইন; ' ফাইলের নাম
মিঃ মুশকরাত

ত্রুটিযুক্ত ... লিঙ্কযুক্ত সাইট, এটি
নাথান ফেলম্যান

আমি এই কোডটির বিপরীতে কেবল একটি এন-লাইন সংস্করণ বেনমার্ক করেছি shuf। পার্ল কোডটি খুব সামান্য দ্রুত (ব্যবহারকারী সময় অনুসারে 8% দ্রুত, সিস্টেম সময় দ্বারা 24% দ্রুত) যদিও উপাহ্যভাবে আমি পার্ল কোডটি "মনে হয়" কম এলোমেলোভাবে পেয়েছি (আমি এটি ব্যবহার করে একটি জুকবক্স লিখেছি)।
অ্যাডাম কাটজ

2
চিন্তার জন্য আরও খাবার: shufসম্পূর্ণ ইনপুট ফাইলটিকে মেমরিতে সঞ্চয় করে , যা একটি ভয়ঙ্কর ধারণা, যখন এই কোডটি কেবল একটি লাইন সঞ্চয় করে, তাই এই কোডটির সীমা INNMAMA এর একটি লাইন গণনা (2 ^ 31 বা 2 ^ 63 আপনার উপর নির্ভর করে) খিলান), এর নির্বাচিত সম্ভাব্য লাইনগুলির কোনও স্মরণে ফিট করে।
অ্যাডাম কাটজ

11

একটি বাশ স্ক্রিপ্ট ব্যবহার:

#!/bin/bash
# replace with file to read
FILE=tmp.txt
# count number of lines
NUM=$(wc - l < ${FILE})
# generate random number in range 0-NUM
let X=${RANDOM} % ${NUM} + 1
# extract X-th line
sed -n ${X}p ${FILE}

1
র‌্যান্ডম 0 হতে পারে, প্রথম লাইনের জন্য সেডের প্রয়োজন 1 needs সেড-এন 0 পি ত্রুটি প্রদান করে।
আসসালোমন 74৪

mhm - "tmp.txt" এর জন্য $ 1 এবং NUM এর জন্য? 2 কেমন?
blabla999

তবে এটি একটি পয়েন্টের মূল্যযুক্ত বাগের সাথেও যেমন পার্ল বা পাইথনের প্রয়োজন হয় না এবং এটি যেমন আপনি পেতে পারেন তত দক্ষ (ফাইলটি ঠিক দু'বার পড়লেও মেমোরিতে নয় - সুতরাং এটি বিশাল ফাইলগুলি নিয়েও কাজ করবে)।
blabla999

@ আসালমন 74৪: ধন্যবাদ @ ব্লেবলা ৯৯৯: যদি আমরা এর বাইরে কোনও ফাংশন করি তবে ঠিক $ 1 এর জন্য, তবে কেন NUM টি গণনা করা হচ্ছে না?
পাওলো টেডেস্কো

সেড লাইনটি এতে পরিবর্তন করা হচ্ছে: মাথা - {{X} $ {ফাইল} | লেজ -1 এটি করা উচিত
জেফকে

4

একক বাশ লাইন:

sed -n $((1+$RANDOM%`wc -l test.txt | cut -f 1 -d ' '`))p test.txt

সামান্য সমস্যা: নকল ফাইলের নাম।


2
হালকা সমস্যা / usr / share / আদেশ / শব্দগুলিতে এটি সম্পাদন করা "A" দিয়ে শুরু হওয়া শব্দের পক্ষে যায়। এটি খেলতে গিয়ে আমি প্রায় 90% "A" শব্দ থেকে 10% "বি" শব্দে আছি। এখনও কোনও সংখ্যা দিয়ে শুরু হয় নি, যা ফাইলের মাথা তৈরি করে।
বিবি

wc -l < test.txtযাও পাইপ থাকার এড়ানো cut
ফেডরকিই 'এসও ক্ষতিগ্রস্থ হওয়া বন্ধ করুন'

3

এখানে একটি সাধারণ পাইথন স্ক্রিপ্ট যা কাজটি করবে:

import random, sys
lines = open(sys.argv[1]).readlines()
print(lines[random.randrange(len(lines))])

ব্যবহার:

python randline.py file_to_get_random_line_from

1
এটি বেশ কাজ করে না। এটি একক লাইনের পরে থামে। এটি কাজ করতে, আমি এটি করেছি: import random, sys lines = open(sys.argv[1]).readlines() আমি সীমার মধ্যে (লেন (লাইন)): র‌্যান্ড = এলোমেলো.রেন্ডিন্ট (0, লেন (লাইন) -1) মুদ্রণ লাইন.পপ (র্যান্ড),
জেড ড্যানিয়েলস

কৃপণ বিন্যাস সহ মূ .় মন্তব্য সিস্টেম। মন্তব্যে ফর্ম্যাট করা কি একবারে কাজ করেনি?
জেড ড্যানিয়েলস

র্যান্ডিন্ট অন্তর্ভুক্ত তাই len(lines)সূচিপত্রের দিকে নিয়ে যেতে পারে। আপনি ব্যবহার করতে পারে print(random.choice(list(open(sys.argv[1]))))। স্মৃতিশক্তি দক্ষ জলাধার স্যাম্পলিং অ্যালগরিদম এছাড়াও আছে ।
jfs

2
খালি জায়গা ক্ষুধার্ত; একটি 3 টিবি ফাইল বিবেচনা করুন।
মাইকেল ক্যাম্পবেল

@ মিশেল ক্যাম্পবেল: জলের জলাশয়ের স্যাম্পলিং অ্যালগরিদম আমি উপরে উল্লেখ করেছি যে 3 টিবি ফাইল (যদি লাইনের আকার সীমাবদ্ধ থাকে) দিয়ে কাজ করতে পারে।
jfs

2

' Awk ' ব্যবহারের অন্য উপায়

awk NR==$((${RANDOM} % `wc -l < file.name` + 1)) file.name

2
এটি awk এবং ব্যাশ ব্যবহার করে ( $RANDOMএটি একটি বাশিজম )। উপরে @ ট্র্যাকার 1 এর উদ্ধৃত পারফ্যালাক 5 কোডের মতো একই যুক্তি ব্যবহার করে একটি খাঁটি অজগর (মওক) পদ্ধতি রয়েছে: awk 'rand() * NR < 1 { line = $0 } END { print line }' file.name(বাহ, এটি পার্ল কোডের চেয়েও খাটো !)
অ্যাডাম কাটজ

wcলাইন গণনা পেতে সেই কোডটি অবশ্যই ফাইল ( ) পড়তে হবে, তারপরে awkপ্রদত্ত এলোমেলো লাইন নম্বরটির সামগ্রী পেতে ফাইলটি আবার (অংশ) পড়তে হবে । I / O এলোমেলো নম্বর পাওয়ার চেয়ে অনেক বেশি ব্যয়বহুল হবে। আমার কোডটি কেবল একবার ফাইলটি পড়ে। অ্যাজকের সমস্যাটি rand()হ'ল এটি সেকেন্ডের উপর ভিত্তি করে বীজ বজায় রাখে , তাই আপনি যদি এটিকে টানা খুব দ্রুত চালনা করেন তবে নকল পাবেন।
অ্যাডাম কাটজ

1

এমন একটি সমাধান যা ম্যাকোএসএক্স-এও কাজ করে এবং লিনাক্স (?) এও কাজ করে:

N=5
awk 'NR==FNR {lineN[$1]; next}(FNR in lineN)' <(jot -r $N 1 $(wc -l < $file)) $file 

কোথায়:

  • N আপনি চান এলোমেলো রেখার সংখ্যা

  • NR==FNR {lineN[$1]; next}(FNR in lineN) file1 file2 -> লিখিত নম্বরগুলি সংরক্ষণ করুন file1এবং তারপরে সংশ্লিষ্ট লাইনটি প্রিন্ট করুনfile2

  • jot -r $N 1 $(wc -l < $file)-> এর সাথে পরিসীমা Nএলোমেলোভাবে সংখ্যা আঁকুন । প্রক্রিয়া প্রতিস্থাপন এটি দোভাষীর ফাইলের মতো দেখায়, সুতরাং আগের উদাহরণে।-r(1, number_of_line_in_file)jot<()file1

0
#!/bin/bash

IFS=$'\n' wordsArray=($(<$1))

numWords=${#wordsArray[@]}
sizeOfNumWords=${#numWords}

while [ True ]
do
    for ((i=0; i<$sizeOfNumWords; i++))
    do
        let ranNumArray[$i]=$(( ( $RANDOM % 10 )  + 1 ))-1
        ranNumStr="$ranNumStr${ranNumArray[$i]}"
    done
    if [ $ranNumStr -le $numWords ]
    then
        break
    fi
    ranNumStr=""
done

noLeadZeroStr=$((10#$ranNumStr))
echo ${wordsArray[$noLeadZeroStr]}

যেহেতু ND র্যান্ডোম / ইউএসআর / শেয়ার / ডিক / শব্দের শব্দের সংখ্যার চেয়ে কম সংখ্যা উত্পন্ন করে, যার 235886 (আমার ম্যাকে যাই হোক), আমি কেবল 0 এবং 9 এর মধ্যে 6 পৃথক এলোমেলো সংখ্যা উত্পন্ন করি এবং সেগুলি এক সাথে স্ট্রিং করি। তারপরে আমি নিশ্চিত করে নিই যে সংখ্যাটি 235886 এর চেয়ে কম। যেহেতু প্রতিটি শব্দের নিজস্ব লাইন এটি যেকোনও ফাইলের জন্য এলোমেলোভাবে একটি লাইন বাছাই করতে সহজেই ব্যবহৃত হতে পারে।
কেন

0

আমার ম্যাক ওএস সমস্ত সহজ উত্তর ব্যবহার করে না বলে আমি এখানে আবিষ্কার করেছি। আমি জট কমান্ডটি একটি সংখ্যা তৈরি করতে ব্যবহার করেছি যেহেতু $ RANDOM পরিবর্তনশীল সমাধানগুলি আমার পরীক্ষায় খুব এলোমেলো মনে হচ্ছে না। আমার সমাধানটি পরীক্ষা করার সময় আমার আউটপুট সরবরাহকৃত সমাধানগুলির মধ্যে বিস্তৃত পরিবর্তন ছিল।

  RANDOM1=`jot -r 1 1 235886`
   #range of jot ( 1 235886 ) found from earlier wc -w /usr/share/dict/web2
   echo $RANDOM1
   head -n $RANDOM1 /usr/share/dict/web2 | tail -n 1

ভেরিয়েবলের প্রতিধ্বনি হ'ল উত্পাদিত এলোমেলো সংখ্যার ভিজ্যুয়াল পাওয়া।


0

কেবল ভ্যানিলা সেড এবং অ্যাজক ব্যবহার করা এবং ILE র্যান্ডোম ব্যবহার না করেই একটি সরল, স্পেস-দক্ষ এবং যুক্তিসঙ্গতভাবে দ্রুত "ওয়ান-লাইনার" ফাইলের নাম হিসাবে ফাইল ফাইল থেকে সিউডো-এলোমেলোভাবে নির্বাচন করার জন্য নিম্নরূপ:

sed -n $(awk 'END {srand(); r=rand()*NR; if (r<NR) {sub(/\..*/,"",r); r++;}; print r}' FILENAME)p FILENAME

(এটি FILENAME খালি থাকা সত্ত্বেও কাজ করে, এক্ষেত্রে কোনও লাইন নির্গত হয় না))

এই পদ্ধতির সম্ভাব্য সুবিধা হ'ল এটি একবারে কেবল র্যান্ড () কল করে।

মন্তব্যগুলিতে @ অ্যাডাম ক্যাটজ দ্বারা চিহ্নিত হিসাবে, আরও একটি সম্ভাবনা প্রতিটি লাইনের জন্য র্যান্ড () কল করা হবে:

awk 'rand() * NR < 1 { line = $0 } END { print line }' FILENAME

(অন্তর্ভুক্তির ভিত্তিতে নির্ভুলতার একটি সহজ প্রমাণ দেওয়া যেতে পারে))

সম্পর্কে গুহা rand()

"গাওক সহ বেশিরভাগ বিশৃঙ্খলা বাস্তবায়নে, র্যান্ড () প্রতিটি বার যখন আপনি খালি চালায় তখন একই প্রারম্ভিক নম্বর বা বীজ থেকে সংখ্যা উত্পন্ন করতে শুরু করে।"

- https://www.gnu.org/software/gawk/manual/html_node/Numeric-Funifications.html


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