Comment puis-je remplacer de manière aléatoire des chaînes spécifiques d'un fichier texte par des chaînes d'un autre fichier? Par exemple:
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]
Si vous vraiment voulez une sélection aléatoire, procédez comme suit: 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 si vous voulez une permutation aléatoire des adresses, je suggère quelque chose comme
paste -d '' <(cut -d'@' -f1 file1.txt) <(sort -R file2.txt)
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Vous pouvez implémenter cet algorithme:
file2.txt
dans un tableaufile1.txt
: Comme ça:
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
(Un merci spécial à @GlennJackman et @dessert pour les améliorations.)
Vous pouvez utiliser shuf
(vous aurez peut-être besoin de Sudo apt install shuf
) pour mélanger les lignes du deuxième fichier, puis les utiliser pour remplacer:
$ 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
randomise simplement l'ordre de ses lignes d'entrée. La commande awk
lira d’abord tout le fichier1 (NR==FNR
ne sera vraie que pendant la lecture du premier fichier) et enregistrera le deuxième champ (les champs sont définis par @
, donc c’est le domaine) dans le tableau associatif a
nom__ dont les valeurs sont les domaines et dont les clés sont les numéros de ligne. Ensuite, lorsque nous arriverons au fichier suivant, il imprimera simplement ce qui était stocké dans a
pour ce numéro de ligne, ainsi que le contenu du fichier 2 pour le même numéro de ligne.
Notez que cela suppose que les deux fichiers ont exactement le même nombre de lignes et ne sont pas réellement "aléatoires", car cela ne permet pas de répéter quoi que ce soit. Mais cela ressemble à ce que vous vouliez demander.
Cette solution remplace la première occurrence d'une seule chaîne donnée arbitraire (l '"aiguille") dans chaque ligne du fichier d'entrée par une chaîne chaque fois choisie aléatoirement parmi l'ensemble des lignes de la liste de chaînes de remplacement.
#!/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))
Il devrait être presque trivial d’ancrer l’aiguille au début ou à la fin de la chaîne ou d’utiliser des expressions régulières.
python replace-random.py NEEDLE REPLACEMENTS-FILE [INPUT-FILE]
Exemple:
python replace-random.py '@address.com' file2.txt file1.txt
ou
python replace-random.py '@address.com' file2.txt < file1.txt
Voici un moyen 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;
Une autre solution bash. Il utilise la fonctionnalité de remplacement de chaîne intégrée bash. Il suppose également que file2.txt
contient uniquement les chaînes de remplacement. Sinon, ils peuvent être d'abord filtrés à l'aide de 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
(presque pur bash
)Ici, nous devons d’abord créer une fonction qui imite shuf
comme si
bshuf ()
{
nlines=$(( $(wc -l < $1) + 1))
Rand=0
while [ "$Rand" -eq 0 ]; do
Rand=$(( $RANDOM % nlines ))
done
echo $(head -n $Rand $1 | tail -1)
}
Alors c'est pareil
for lines in $(grep $Search file1.txt)
do
echo ${lines/$Search/$(bshuf file2.txt)}
done
Tester:
$ 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]
$