Como substituir texto aleatoriamente do arquivo?

9

Como posso substituir aleatoriamente strings específicas em um arquivo de texto com strings de outro arquivo? Por exemplo:

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]
    
por elanozturk 17.12.2017 / 16:37

6 respostas

9

Se você realmente quiser uma seleção aleatória, então aqui está uma maneira de usar 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 se você quiser uma permutação aleatória dos endereços, eu sugiro algo como

paste -d '' <(cut -d'@' -f1 file1.txt) <(sort -R file2.txt)
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
    
por steeldriver 17.12.2017 / 17:07
10

Você pode implementar esse algoritmo:

  • Carregue o conteúdo de file2.txt em uma matriz
  • Para cada linha em file1.txt :
    • Extraia a parte do nome
    • Obter um endereço aleatório
    • Imprima a saída corretamente formatada

Assim:

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

(Agradecimentos especiais a @GlennJackman e @dessert pelas melhorias.)

    
por janos 17.12.2017 / 16:45
5

Você pode usar shuf (talvez seja necessário sudo apt install shuf ) para embaralhar as linhas do segundo arquivo e usá-las para substituir:

$ 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 simplesmente randomiza a ordem de suas linhas de entrada. O comando awk lerá primeiro todo o arquivo1 ( NR==FNR só será verdadeiro enquanto o primeiro arquivo estiver sendo lido) e salvará o segundo campo (os campos são definidos por @ , então este é o domínio) em a matriz associativa a cujos valores são os domínios e cujas chaves são os números de linha. Então, quando chegarmos ao próximo arquivo, ele simplesmente imprimirá o que estava armazenado em a para esse número de linha, junto com o que está no arquivo 2 para o mesmo número de linha.

Note que isso pressupõe que ambos os arquivos tenham exatamente o mesmo número de linhas e não estejam sendo "aleatórios", já que não permitirá que nada seja repetido. Mas isso parece com o que você queria perguntar.

    
por terdon 17.12.2017 / 17:08
5

Solução Python 2.7 e 3

Esta solução substitui a primeira ocorrência de uma única string arbitrária dada (a "agulha") em cada linha do arquivo de entrada com uma string cada vez escolhida aleatoriamente a partir do conjunto de linhas da lista de strings de substituição.

#!/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))

Deve ser quase trivial ancorar a agulha no começo ou no final da string ou usar expressões regulares.

Uso

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

Exemplo:

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

ou

python replace-random.py '@address.com' file2.txt < file1.txt
    
por David Foerster 17.12.2017 / 22:54
3

Aqui está um caminho 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;
    
por Josh 18.12.2017 / 01:32
2

Outra solução bash. Ele usa o recurso de substituição de strings integrado do bash. Ele também assume file2.txt contém apenas as seqüências de substituição. Se não, eles podem ser filtrados primeiro usando grep -o <replace> file2.txt

com shuf

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

Sem shuf (quase puro bash )

Aqui temos que criar primeiro uma função que imite shuf , assim como

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

Então é semelhante

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

Teste:

$ 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]
$ 
    
por SigmaPiEpsilon 17.12.2017 / 22:47