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


9

আমি কীভাবে এলোমেলোভাবে অন্য ফাইলের স্ট্রিং সহ একটি পাঠ্য ফাইলে নির্দিষ্ট স্ট্রিংগুলি প্রতিস্থাপন করতে পারি? উদাহরণ স্বরূপ:

file1.txt(file has more than 200 lines):
moonwalker@address.com
hansolo@address.com
anakinskywalker@address.com
obiwankenobi@address.com
darthvader@address.com

file2.txt(file has 10-20 lines):
@adress1.com
@adress2.com
@adress3.com
@adress4.com
@adress5.com

output.txt:
moonwalker@address4.com
hansolo@address1.com
anakinskywalker@address5.com
obiwankenobi@address2.com
darthvader@address3.com

4
এটি এলোমেলো নয়, দেখে মনে হচ্ছে আপনি কিছু পুনরাবৃত্তি করতে চান না। আপনি কি এটিকে প্রকৃতপক্ষে এলোমেলো করতে চান বা দ্বিতীয় পাঠ্য ফাইলের প্রতিটি লাইন একবারে ব্যবহার করা উচিত? এছাড়াও, এটি কি বাশ করা দরকার , না আপনি অন্য সরঞ্জামের জন্য উন্মুক্ত?
টেরডন

1
@ ইটারডন দেখে মনে হচ্ছে তিনি এলোমেলোভাবে ক্রম ছাড়তে চান (সমস্ত 5 টি উপাদান তবে একটি এলোমেলো ক্রমে)। একটি এলোমেলো ক্রমায়নটি আসলে এলোমেলোভাবে, এলোমেলোভাবে পরবর্তী উপাদানটি নির্বাচন করার সময় আপনাকে কেবল ইতিমধ্যে নির্বাচিত উপাদানগুলি অপসারণ করতে হবে। কখনও কখনও একটি "এলোমেলো বাছাই" নামে পরিচিত
থোমাসরুতার

1
@ থমাসরুতর হ্যাঁ, আমি এটি জানি এবং এটিই আমার উত্তরটি দেয়। তবে সে কারণেই আমি ওপিকে স্পষ্ট করে বলতে বলছিলাম যেহেতু এলোমেলো ক্রমুয়েশন এবং একটি এলোমেলো বাছাই উভয়ই যা প্রয়োজন তা নির্ভর করে যুক্তিসঙ্গত হবে।
টের্ডন

উত্তর:


9

আপনি যদি সত্যিই এলোমেলো নির্বাচন চান, তবে এখানে একটি উপায় ব্যবহার করুন awk:

awk '
  BEGIN{FS="@"; OFS=""} 
  NR==FNR{a[NR]=$0; n++; next} 
  {$2=a[int(1 + n * rand())]; print}
' file2.txt file1.txt
moonwalker@adress2.com
hansolo@adress2.com
anakinskywalker@adress5.com
obiwankenobi@adress1.com
darthvader@adress3.com

OTOH যদি আপনি ঠিকানাগুলির একটি এলোমেলোভাবে অনুচ্ছেদ পেতে চান তবে আমি এর মতো কিছু প্রস্তাব দেব

paste -d '' <(cut -d'@' -f1 file1.txt) <(sort -R file2.txt)
moonwalker@adress2.com
hansolo@adress1.com
anakinskywalker@adress5.com
obiwankenobi@adress4.com
darthvader@adress3.com

1
নিস! আমি এটির সাথে কাজ করার দিকে নজর দিচ্ছিলাম pasteতবে এটি cutঅ-ম্যাচিং ক্ষেত্রটি সরাতে আমার ব্যবহার হয় নি।
টেরডন

2
পেস্ট দ্রষ্টব্যটির একটি খারাপ দিকটি যখন ফাইল 1-তে ফাইল 2 এর চেয়ে বেশি লাইন থাকে। পরিবর্তে <(sort -R file2.txt)আমরা এর মতো কিছু ব্যবহার করতে পারি <(yes "$(<file2.txt)" | head -n $(wc -l < file1.txt) | sort -R)- যা ফাইল 2 এর শীর্ষের কাছাকাছি রেখার পক্ষে এলোমেলোতার স্কিও করতে পারে।
গ্লেন জ্যাকম্যান

10

আপনি এই অ্যালগরিদম প্রয়োগ করতে পারেন:

  • file2.txtএকটি অ্যারেতে সামগ্রী লোড করুন
  • প্রতিটি লাইনের জন্য file1.txt:
    • নামের অংশটি বের করুন
    • একটি এলোমেলো ঠিকানা পান
    • আউটপুট সঠিকভাবে ফর্ম্যাট করা মুদ্রণ করুন

এটার মত:

mapfile -t addresses < file2.txt
while IFS='' read -r orig || [[ -n "$orig" ]]; do
    ((index = RANDOM % ${#addresses[@]}))
    name=${orig%%@*}
    echo "$name${addresses[index]}"
done < file1.txt

(উন্নতির জন্য @ গ্লেন জ্যাকম্যান এবং @ ডেজার্টকে বিশেষ ধন্যবাদ thanks)


3
আপনি অ্যারের সাথে পপুলেটিংয়ের কথা বিবেচনা করতে পারেন mapfile -t addresses < file2.txt- catসেই জাতীয় বিষয়গুলি ব্যবহার করে আপনি শব্দ বিভাজন এবং ফাইলের নাম সম্প্রসারণ করতে পারেন।
গ্লেন জ্যাকম্যান

2
file1.txtএই ফাইলটি যদি এই ফাইলটি খালি লাইনের সাথে শেষ না হয় তবে এটির শেষ নন-খালি লাইনটি ধরা আছে (দুঃখিত, এই মুহুর্তে পরীক্ষা করতে পারবেন না)? আমি যদি সুপারিশ না করি তবে ভেরিয়েবল · এসওকে মূল্য নির্ধারণ করে লাইন দিয়ে একটি ফাইল লাইন পড়ুনwhile IFS='' read -r orig || [[ -n "$orig" ]]; do দেখুন ।
ডেজার্ট

2
@ জ্যানোস এই বিষয়টিতে সবেমাত্র একটি খুব ভাল প্রশ্ন পেয়েছে: শেল স্ক্রিপ্টটি শেষ পংক্তিটি হারিয়েছে
মিষ্টান্ন

5

আপনি দ্বিতীয় ফাইলের লাইনগুলি বদলাতে এবং তারপরে প্রতিস্থাপনের জন্য এটি ব্যবহার করতে পারেন shuf(আপনার প্রয়োজন হতে পারে sudo apt install shuf):

$ awk -F'@' 'NR==FNR{a[NR]=$1;next}{print a[FNR]"@"$2} ' file1 <(shuf file2)
moonwalker@adress3.com
hansolo@adress1.com
anakinskywalker@adress5.com
obiwankenobi@adress4.com
darthvader@adress2.com

shufকেবল তার ইনপুট লাইনের ক্রমটি এলোমেলো করে। awkকমান্ড প্রথম file1 এর সমস্ত (পড়তে হবে NR==FNRযখন প্রথম ফাইলটি হচ্ছে পঠিত একমাত্র সত্য হবে), এবং দ্বিতীয় ক্ষেত্র সংরক্ষণ (ক্ষেত্র দ্বারা সংজ্ঞায়িত করা হয় @এসসিয়েতিভ আরে, তাই এই ডোমেইন হয়) aযার মান ডোমেইনের এবং যার কীগুলি লাইন নম্বর। তারপরে, আমরা যখন পরবর্তী ফাইলটিতে পৌঁছব aতখন একই লাইন নম্বরটির জন্য ফাইল 2 এ যা আছে তা বরাবর এটি সহজেই মুদ্রণ করবে ।

নোট করুন যে এটি ধরে নিয়েছে যে উভয় ফাইলেরই ঠিক একই সংখ্যক লাইন রয়েছে এবং এটি আসলে "এলোমেলো" নয়, কারণ এটি কোনও কিছুর পুনরাবৃত্তি করতে দেয় না। তবে আপনি যা চেয়েছিলেন তা দেখে মনে হচ্ছে এটি।


5

পাইথন 2.7 এবং 3 সমাধান

এই সমাধানটি প্রতিস্থাপনের স্ট্রিং তালিকার লাইনের সেট থেকে এলোমেলোভাবে বেছে নেওয়া প্রতিটি বারের সাথে ইনপুট ফাইলের প্রতিটি লাইনটিতে একটি একক স্বেচ্ছাকৃত প্রদত্ত স্ট্রিংয়ের ("সুই") প্রতিস্থাপন করে।

#!/usr/bin/python
from __future__ import print_function
import sys, random

needle = sys.argv[1]

if sys.argv[2] == '-':
    f_replacements = sys.stdin
else:
    f_replacements = open(sys.argv[2])
with f_replacements:
    replacements = [l.rstrip('\n') for l in f_replacements]
if not replacements:
    raise ValueError('No replacement strings given')

if len(sys.argv) <= 3 or sys.argv[3] == '-':
    f_in = sys.stdin
else:
    f_in = open(sys.argv[3])
with f_in:
    for s in f_in:
        rep = replacements[random.randrange(len(replacements))]
        print(s.rstrip('\n').replace(needle, rep, 1))

স্ট্রিংয়ের শুরু বা শেষের সূঁচটি অ্যাঙ্কর করা বা নিয়মিত এক্সপ্রেশন পুরোপুরি ব্যবহার করার জন্য এটি প্রায় তুচ্ছ হওয়া উচিত।

ব্যবহার

python replace-random.py NEEDLE REPLACEMENTS-FILE [INPUT-FILE]

উদাহরণ:

python replace-random.py '@address.com' file2.txt file1.txt

অথবা

python replace-random.py '@address.com' file2.txt < file1.txt

3

এখানে একটি পার্ল উপায়:

#!/usr/bin/perl
use warnings;
use strict;
use Tie::File;

tie my @file1,'Tie::File','file1.txt' or die "Can't open file1.txt\n";
tie my @file2,'Tie::File','file2.txt' or die "Can't open file2.txt\n";

for my $file_index (0..$#file1) {
   my $suffix = $file2[int(rand($#file2+1))];
   $file1[$file_index] =~ s/@.*$/$suffix/;
}

untie @file1;
untie @file2;

2

আরেকটি বাশ সমাধান। এটি ব্যাশ অন্তর্নির্মিত স্ট্রিং প্রতিস্থাপন বৈশিষ্ট্য ব্যবহার করে। এটি ধরে নেয় file2.txtকেবল প্রতিস্থাপনের স্ট্রিং রয়েছে। তা না হলে এগুলি ব্যবহার করে প্রথমে ফিল্টার করা যায়grep -o <replace> file2.txt

সঙ্গে shuf

#search string
Search="@address.com"
for lines in $(grep $Search file1.txt)
do 
    echo ${lines/$Search/$(shuf file2.txt -n 1)} 
done

ছাড়া shuf(প্রায় খাঁটি bash)

এখানে আমাদের প্রথমে একটি ফাংশন তৈরি করতে হবে যা shufপছন্দ করে m

bshuf () 
{ 
    nlines=$(( $(wc -l < $1) + 1))
    rand=0
    while [ "$rand" -eq 0 ]; do
        rand=$(( $RANDOM % nlines ))
    done
    echo $(head -n $rand $1 | tail -1)
}

তারপরেও এটি একই রকম

for lines in $(grep $Search file1.txt) 
do 
    echo ${lines/$Search/$(bshuf file2.txt)}
done

টেস্ট:

$ for lines in $(grep $Search file1.txt); do echo ${lines/$Search/$(bshuf file2.txt)} ; done
moonwalker@adress4.com
hansolo@adress2.com
anakinskywalker@adress2.com
obiwankenobi@adress3.com
darthvader@adress5.com
$ 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.