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

Я не могу прокомментировать, так что отправьте ответ, как Ubuntu 16.04, с ядром 4.10.

@ Ответ Ричарда для меня недостаточен, а трюк @ user590496 необходим. Кредиты идут на @Richard и @ user590496, но я также суммирую шаги:

Установите протокол интернет-печати:
sudo apt install libcupsimage2:i386
Установите библиотеки C ++, сжатия и ncurses (32-разрядные версии работали для моей 64-битной системы ):
sudo apt install lib32stdc++6 lib32z1 lib32ncurses5
Загрузите и установите драйвер Xerox Phaser 6000. Установите принтер из системных настроек.
9
задан 18 December 2017 в 05:36

10 ответов

Если вам действительно нужен случайный выбор, вот один из способов: [! f3]:

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, если вы хотите случайную перестановку адресов, я бы предложил что-то вроде [!d2 ]

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
9
ответ дан 22 May 2018 в 16:56
  • 1
    Ницца! Я изучал это с помощью paste, но мне не приходило в голову использовать cut для удаления поля несоответствия. – terdon♦ 17 December 2017 в 20:09
  • 2
    Один недостаток решения пасты - когда файл1 имеет больше строк, чем file2. Вместо <(sort -R file2.txt) мы можем использовать что-то вроде <(yes "$(<file2.txt)" | head -n $(wc -l < file1.txt) | sort -R) - которые могут исказить случайность в пользу линий, расположенных ближе к вершине файла2. – glenn jackman 17 December 2017 в 20:27

Вы можете реализовать этот алгоритм:

Загрузите содержимое file2.txt в массив Для каждой строки в file1.txt: Извлечь часть имени Получить произвольный адрес Печатать вывод правильно отформатированный [!d1 ]

Как это:

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 за улучшения.)

10
ответ дан 22 May 2018 в 16:56
  • 1
    Вы можете подумать о том, чтобы заполнить массив с помощью mapfile -t addresses < file2.txt - используя cat, как это, вы можете разделить слово и расширение имени файла. – glenn jackman 17 December 2017 в 20:22
  • 2
    Означает ли это последнюю непустую строку file1.txt, если этот файл не заканчивается пустой строкой (извините, не может проверить на данный момент)? Если нет, рекомендую while IFS='' read -r orig || [[ -n "$orig" ]]; do, см. Прочитать строку строки по строке, присваивая значение переменной · SO . – dessert 17 December 2017 в 21:31
  • 3
    @janos Просто нашел очень хороший вопрос по теме: Сценарий оболочки прочитал пропущенную последнюю строку – dessert 18 December 2017 в 20:34

Вы можете использовать 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 там сначала прочитает весь файл1 (NR==FNR будет истинным только во время чтения первого файла) и сохранит второе поле (поля определены @, так что это домен) в ассоциативный массив a, значения которого являются доменами и чьими ключами являются номера строк. Затем, когда мы перейдем к следующему файлу, он просто распечатает все, что было сохранено в a для этого номера строки, а также то, что находится в файле 2 для того же номера строки.

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

5
ответ дан 22 May 2018 в 16:56

Решение 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
5
ответ дан 22 May 2018 в 16:56

Вот путь 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;
3
ответ дан 22 May 2018 в 16:56

Другое решение 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

Test:

$ 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
$ 
2
ответ дан 22 May 2018 в 16:56

Решение 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
5
ответ дан 18 July 2018 в 01:00

Другое решение 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

Test:

$ 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 $
2
ответ дан 18 July 2018 в 01:00

Решение 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
5
ответ дан 24 July 2018 в 17:19

Другое решение 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

Test:

$ 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 $
2
ответ дан 24 July 2018 в 17:19
  • 1
    Ницца! Я изучал это с помощью paste, но мне не приходило в голову использовать cut для удаления поля несоответствия. – terdon♦ 17 December 2017 в 20:09
  • 2
    Вы можете подумать о том, чтобы заполнить массив с помощью mapfile -t addresses < file2.txt - используя cat, как это, вы можете разделить слово и расширение имени файла. – glenn jackman 17 December 2017 в 20:22
  • 3
    Один недостаток решения пасты - когда файл1 имеет больше строк, чем file2. Вместо <(sort -R file2.txt) мы можем использовать что-то вроде <(yes "$(<file2.txt)" | head -n $(wc -l < file1.txt) | sort -R) - которые могут исказить случайность в пользу линий, расположенных ближе к вершине файла2. – glenn jackman 17 December 2017 в 20:27
  • 4
    Означает ли это последнюю непустую строку file1.txt, если этот файл не заканчивается пустой строкой (извините, не может проверить на данный момент)? Если нет, рекомендую while IFS='' read -r orig || [[ -n "$orig" ]]; do, см. [D0] Прочитать строку строки по строке, присваивая значение переменной · SO . – dessert 17 December 2017 в 21:31
  • 5
    @janos Просто нашел очень хороший вопрос по теме: Сценарий оболочки прочитал пропущенную последнюю строку – dessert 18 December 2017 в 20:34

Другие вопросы по тегам:

Похожие вопросы: