একটি পাঠ্য ফাইল থেকে এলোমেলো রেখা কীভাবে প্রদর্শন করবেন?


26

আমি শেল স্ক্রিপ্ট লেখার চেষ্টা করছি। ধারণাটি হ'ল পাঠ্য ফাইল থেকে এলোমেলোভাবে একটি একক লাইন নির্বাচন করা এবং এটি একটি উবুন্টু ডেস্কটপ বিজ্ঞপ্তি হিসাবে প্রদর্শন করা।

তবে আমি চাইছি প্রতিবার স্ক্রিপ্টটি সম্পাদন করে বিভিন্ন লাইন নির্বাচন করা হোক। এটি করার কোনও সমাধান আছে কি? আমি পুরো স্ক্রিপ্ট চাই না। শুধু যে সহজ জিনিস।


এছাড়াও এখানে যান: askubuntu.com/q/492572/256099
পান্ড্য

উত্তর:


40

আপনি shufফাইল থেকে এলোমেলো লাইন মুদ্রণ করতে ইউটিলিটি ব্যবহার করতে পারেন

$ shuf -n 1 filename

-n : মুদ্রণের জন্য লাইনের সংখ্যা

উদাহরণ:

$ shuf -n 1 /etc/passwd

git:x:998:998:git daemon user:/:/bin/bash

$ shuf -n 2 /etc/passwd

avahi:x:84:84:avahi:/:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false

তবে এটি ব্যবহার করে, আমাকে ম্যানুয়ালি সঠিকভাবে n এর মানটি পরিবর্তন করতে হবে? আমি চাই যে শেলটি স্বয়ংক্রিয়ভাবে এলোমেলোভাবে অন্য একটি লাইন বেছে নেবে। এলোমেলোভাবে ঠিক হওয়ার দরকার নেই। তবে অন্য কিছু লাইন।
আনন্দু এম দাস

4
@ আনানডুএমডাস না, আপনাকে nমুদ্রণের জন্য লাইনের সংখ্যা বোঝাতে হবে না । (যেমন আপনি কেবল একটি লাইন বা দুটি লাইন চান)। লাইন নম্বর নয় (যেমন প্রথম লাইন দ্বিতীয় লাইন)।
aneeshep

@ আনন্দমাদাস: আমি আমার উত্তরে কয়েকটি উদাহরণ যুক্ত করেছি। আশা করি এটি এখন পরিষ্কার হয়ে যাবে।
এনিশপ

1
ধন্যবাদ আপনাকে এখন এটি পরিষ্কার করা হয়েছে :) আমি আরও একটি অ্যালগরিদম পেয়েছি, এটির মতো, বর্তমান date +%Sসময়টিকে (কেবলমাত্র দ্বিতীয় দ্বারা ) একটি ভেরিয়েবল এক্সে সংরক্ষণ করুন এবং তারপরে টেক্সট ফাইল থেকে headঅ্যান্ড tailকমান্ডগুলি ব্যবহার করে সেই এক্সটি লাইনটি নির্বাচন করুন। যাইহোক আপনার পদ্ধতি আরও সহজ is ধন্যবাদ
আনন্দু এম দাস

+1: shufকোর্টিলগুলিতে রয়েছে তাই এটি ডিফল্টরূপে উপলব্ধ। দ্রষ্টব্য: এটি ইনপুট ফাইলটিকে মেমরিতে লোড করে। একটি দক্ষ অ্যালগরিদম রয়েছে যা এর প্রয়োজন হয় না
jfs

13

আপনি sortফাইলটি থেকে এলোমেলো লাইন পেতে কমান্ডটি ব্যবহার করতে পারেন ।

sort -R filename | head -n1

দ্রষ্টব্য: sort -Rইনপুটটিতে সদৃশ লাইন থাকলে shuf -n1বা তার চেয়ে আলাদা ফলাফল উত্পন্ন করে select-random। দেখুন @ EliahKagan এর মন্তব্য
jfs

8

শুধু মজার জন্য, এখানে একটি হল বিশুদ্ধ ব্যাশ সমাধান যা ব্যবহার করে না shuf, sort, wc, sed, head, tailবা অন্য কোন বাইরের সরঞ্জাম।

shufবৈকল্পিকের একমাত্র সুবিধা হ'ল এটি খাঁটি বাশ, যেহেতু এটি কিছুটা দ্রুত। আমার মেশিনে, 1000 লাইনগুলির একটি ফাইলের জন্য shufভেরিয়েন্টটি প্রায় 0.1 সেকেন্ড সময় নেয়, যখন নিম্নলিখিত স্ক্রিপ্টটি প্রায় 0.01 সেকেন্ড সময় নেয়;) সুতরাং shufসবচেয়ে সহজ এবং সংক্ষিপ্ততম বৈকল্পিকটি এটি দ্রুততর।

shufউচ্চ দক্ষতা একটি গুরুত্বপূর্ণ উদ্বেগ না হলে আমি সমস্ত সততার সাথে এখনও সমাধানের পক্ষে যাব ।

#!/bin/bash

FILE=file.txt

# get line count for $FILE (simulate 'wc -l')
lc=0
while read -r line; do
 ((lc++))
done < $FILE

# get a random number between 1 and $lc
rnd=$RANDOM
let "rnd %= $lc"
((rnd++))

# traverse file and find line number $rnd
i=0
while read -r line; do
 ((i++))
 [ $i -eq $rnd ] && break
done < $FILE

# output random line
printf '%s\n' "$line"

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

জিএনইউ / লিনাক্স / আন * এক্স এর বেশিরভাগ রাস্তা-পরীক্ষিত চাকা রয়েছে যা আমি পুনরায় উদ্ভাবন করতে চাই না, যদি না এটি খাঁটি একাডেমিক অনুশীলন না হয়। "শেল" ইনপুট / আউটপুট এবং প্রচুর পরিমাণে বিকল্পগুলির মাধ্যমে বিভিন্ন উপায়ে একত্রিত হতে পারে এমন প্রচুর বিদ্যমান অংশগুলিকে একত্রিত করার জন্য ব্যবহৃত হয়েছিল। অন্য কোনও কিছুই খারাপ ফর্ম, যদি না এটি খেলাধুলার জন্য থাকে (যেমন, কোডগল্ফ.স্ট্যাকেক্সেক্সঞ্জি.টায়ার ), এক্ষেত্রে খেলুন ...!
মাইকেল 25

2
@ মাইকেল_ন যদিও "খাঁটি বাশ" উপায়টি শেখানোর জন্য এবং অন্যান্য কাজের জন্য সংশোধন করার জন্য মূলত দরকারী তবে এটি বাস্তব হিসাবে বাস্তবের জন্য এটি আরও যুক্তিসঙ্গত। বাশ ব্যাপকভাবে উপলভ্য, তবে shufএর জিএনইউ কোরিউটিলস - নির্দিষ্ট (যেমন, ফ্রিবিএসডি 10.0 তে নেই)। sort -Rপোর্টেবল, তবে একটি পৃথক (সম্পর্কিত) সমস্যা সমাধান করে: একাধিক লাইন হিসাবে উপস্থিত স্ট্রিংগুলির কেবলমাত্র একবার উপস্থিত হওয়ার সমান সম্ভাবনা রয়েছে। (অবশ্যই, wcএবং অন্যান্য ইউটিলিটিগুলি এখনও ব্যবহার করা যেতে পারে)) আমার মনে হয় এখানে মূল সীমাবদ্ধতা হ'ল এটি 32768 তম লাইনের পরে কখনই কিছু গ্রহণ করে না (এবং কিছুটা তাড়াতাড়ি কম এলোমেলো হয়ে যায়)।
এলিয়াহ কাগন

2
মাল্টে স্কোরুপা: আমি দেখতে পেয়েছি আপনি ব্যাশ পিআরএনজি প্রশ্নটি ইউএন্ডএল স্থানান্তরিত করেছেন । কুল। ইঙ্গিত: $((RANDOM<<15|RANDOM))0..2 ^ 30-1 এ। @ জেফেসেবাস্টিয়ান এটি shufনয় sort -R, যা ঘন ঘন ইনপুটগুলির দিকে ঝুঁকে পড়ে। shuf -n 1জায়গায় রাখুন sort -R | head -n1এবং তুলনা করুন। (বিটিডব্লু 10 ^ 3 পুনরাবৃত্তিগুলি 10 ^ 6 এর চেয়ে দ্রুত এবং তফাতটি দেখানোর পক্ষে যথেষ্ট যথেষ্ট)) আরও দেখুন একটি রাউবার, আরও ভিজ্যুয়াল ডেমো এবং এই বিড়ালতা দেখায় এটি বড় ইনপুটগুলিতে কাজ করে যেখানে সমস্ত স্ট্রিং উচ্চ ফ্রিকোয়েন্সি
এলিয়াহ কাগন

1
@ জেফেসেবাস্টিয়ান সেই আদেশে ইনপুটটি dieharderসমস্ত শূন্য বলে মনে হচ্ছে। এটি ধরে নেওয়া আমার পক্ষে কিছু অদ্ভুত ভুল নয়, অবশ্যই এটি ব্যাখ্যা করবে কেন এটি এলোমেলো নয়! আপনি যদি while echo $(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 )); do :; done | perl -ne 'print pack "I>"' > outকিছুক্ষণ চালনা করেন এবং তারপরে outকোনও হেক্স সম্পাদকের সামগ্রীগুলি পরীক্ষা করেন তবে আপনি কী সুদর্শন ডেটা পাবেন ? (বা তবে আপনার পছন্দ মতো এটি দেখুন)) আমি সমস্ত শূন্য পেয়েছি, এবং RANDOMঅপরাধী নয়: আমিও প্রতিস্থাপন করার $(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 ))সাথে সাথে সমস্ত জিরো পেয়ে যাই 100
এলিয়াহ কাগন

4

বলুন আপনার কাছে ফাইল আছে notifications.txt। এলোমেলো জেনারেটরের পরিসর নির্ধারণ করতে আমাদের মোট লাইন সংখ্যা গণনা করতে হবে:

$ cat notifications.txt | wc -l

চলকটিতে লিখতে দেয়:

$ LINES=$(cat notifications.txt | wc -l)

এখন থেকে সংখ্যা তৈরি 0করতে to$LINE আমরা RANDOMভেরিয়েবল ব্যবহার করব ।

$ echo $[ $RANDOM % LINES]

চলকটিতে এটি লিখতে দিন:

$  R_LINE=$(($RANDOM % LINES))

এখন আমাদের কেবল এই লাইন নম্বরটি প্রিন্ট করতে হবে:

$ sed -n "${R_LINE}p" notifications.txt

র‌্যান্ডম সম্পর্কে:

   RANDOM Each time this parameter is referenced, a random integer between
          0 and 32767 is generated.  The sequence of random numbers may be
          initialized by assigning a value to RANDOM.  If RANDOM is unset,
          it  loses  its  special  properties,  even if it is subsequently
          reset.

আপনার ফাইলটিতে 32767 লাইন সংখ্যা কম রয়েছে তা নিশ্চিত হয়ে নিন। দেখ এই যদি আপনি বড় র্যান্ডম জেনারেটরের বাক্সের বাইরে কাজ করে প্রয়োজন।

উদাহরণ:

$ od -A n -t d -N 3 /dev/urandom | tr -d ' '

একটি স্টাইলিস্টিক বিকল্প (বাশ):LINES=$(wc -l < file.txt); R_LINE=$((RANDOM % LINES)); sed -n "${R_LINE}p" file.txt
মাইকেল 25


উদাহরণস্বরূপ, কেন এলোমেলো সংখ্যায় প্রয়োগ করা ভাল ধারণা নয় তা বুঝতে ধূসর বিটম্যাপ ব্যবহার করে টেস্ট PRNG- র শেষ চিত্রটি দেখুন % n
jfs

2

এখানে পাইথন স্ক্রিপ্ট যা ইনপুট ফাইল বা স্টিডিন থেকে একটি এলোমেলো লাইন নির্বাচন করে:

#!/usr/bin/env python
"""Usage: select-random [<file>]..."""
import random

def select_random(iterable, default=None, random=random):
    """Select a random element from iterable.

    Return default if iterable is empty.
    If iterable is a sequence then random.choice() is used for efficiency instead.
    If iterable is an iterator; it is exhausted.
    O(n)-time, O(1)-space algorithm.
    """
    try:
        return random.choice(iterable) # O(1) time and space
    except IndexError: # empty sequence
        return default
    except TypeError: # not a sequence
        return select_random_it(iter(iterable), default, random.randrange)

def select_random_it(iterator, default=None, randrange=random.randrange):
    """Return a random element from iterator.

    Return default if iterator is empty.
    iterator is exhausted.
    O(n)-time, O(1)-space algorithm.
    """
    # from /programming//a/1456750/4279
    # select 1st item with probability 100% (if input is one item, return it)
    # select 2nd item with probability 50% (or 50% the selection stays the 1st)
    # select 3rd item with probability 33.(3)%
    # select nth item with probability 1/n
    selection = default
    for i, item in enumerate(iterator, start=1):
        if randrange(i) == 0: # random [0..i)
            selection = item
    return selection

if __name__ == "__main__":
    import fileinput
    import sys

    random_line = select_random_it(fileinput.input(), '\n')
    sys.stdout.write(random_line)
    if not random_line.endswith('\n'):
        sys.stdout.write('\n') # always append newline at the end

অ্যালগরিদম হ'ল হে (এন) -কালীন, ও (1) -স্পেস। এটি 32767 লাইনের চেয়ে বড় ফাইলগুলির জন্য কাজ করে। এটি মেমোরিতে ইনপুট ফাইলগুলি লোড করে না। এটি প্রতিটি ইনপুট লাইন ঠিক একবার পড়ে reads আপনি এটিতে স্বেচ্ছাসেবী বৃহত (তবে সসীম) সামগ্রীটি পাইপ করতে পারেন। এখানে অ্যালগরিদমের ব্যাখ্যা


1

আমি মাল্ট স্কোরুপা এবং অন্যরা যে কাজটি করেছে তা দেখে আমি মুগ্ধ, তবে এটি করার একটি সহজ সরল "খাঁটি বাশ" উপায় এখানে:

IFS=$'\012'
# set field separator to newline only
lines=( $(<test5) )
# slurp entire file into an array
numlines=${#lines[@]}
# count the array elements
num=$(( $RANDOM$RANDOM$RANDOM % numlines ))
# get a (more-or-less) random number within the correct range
line=${lines[$num]}
# select the element corresponding to the random number
echo $line
# display it

যেমনটি উল্লেখ করেছেন যে, ND র্যান্ডম এলোমেলো নয়। তবে, 32767 লাইনের ফাইলের আকার সীমাটি as RANDOM গুলি একসাথে স্ট্রিং করে কাটিয়ে উঠেছে।

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