Как случайно заменить текст из файла?

9

Как я могу случайным образом заменить определенные строки в одном текстовом файле на строки из другого файла? Например:

file1.txt(file has more than 200 lines):
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

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

output.txt:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
    
задан elanozturk 17.12.2017 в 15:37
источник

6 ответов

9

Если вы действительно хотите случайный выбор, то один из способов: awk :

awk '
  BEGIN{FS="@"; OFS=""} 
  NR==FNR{a[NR]=$0; n++; next} 
  {$2=a[int(1 + n * rand())]; print}
' file2.txt file1.txt
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

OTOH, если вы хотите случайную перестановку адресов, я бы предложил что-то вроде

paste -d '' <(cut -d'@' -f1 file1.txt) <(sort -R file2.txt)
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
    
ответ дан steeldriver 17.12.2017 в 16:07
источник
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

(Особая благодарность @GlennJackman и @dessert за улучшения.)

    
ответ дан janos 17.12.2017 в 15:45
5

Вы можете использовать shuf (вам может понадобиться sudo apt install shuf ), чтобы перетасовать строки второго файла, а затем использовать их для замены:

$ awk -F'@' 'NR==FNR{a[NR]=$1;next}{print a[FNR]"@"$2} ' file1 <(shuf file2)
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

shuf просто рандомизирует порядок своих входных строк. Команда awk сначала прочитает весь файл1 ( NR==FNR будет истинным только при первом чтении файла) и сохранит второе поле (поля определены @ , поэтому это домен) в ассоциативный массив a , значениями которого являются домены и ключи которых являются номерами строк. Затем, когда мы перейдем к следующему файлу, он просто распечатает все, что было сохранено в a для этого номера строки, а также то, что находится в файле 2 для одного номера строки.

Обратите внимание, что это предполагает, что оба файла имеют точно такое же количество строк и на самом деле не являются «случайными», поскольку он не позволит ничего повторять. Но это похоже на то, о чем вы хотели попросить.     

ответ дан terdon 17.12.2017 в 16:08
5

Решение Python 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
    
ответ дан David Foerster 17.12.2017 в 21:54
3

Вот путь perl:

#!/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;
    
ответ дан Josh 18.12.2017 в 00:32
2

Другое решение bash. Он использует встроенную функцию замены строки bash. Он также предполагает, что 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

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
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
$ 
    
ответ дан SigmaPiEpsilon 17.12.2017 в 21:47