awk - взять случайную строку из одного файла и объединить ее со строками из другого файла, вывести в третий файл - PullRequest
1 голос
/ 22 апреля 2020

В приведенной ниже задаче я могу получить случайную строку из файла file1 с помощью awk, и я могу редактировать файл file2 с помощью awk, если я просто записываю фиксированную строку в выходной файл, но если я хочу использовать случайную строку из file1 вместо фиксированная строка, то я застрял. Я не знаю, как вставить код awk, который получает случайную строку, в код, который редактирует файл2 (или эквивалентный подход, который выполняет ту же работу).

file1:

    string1_^%"$"£xxXF%
    string2-$^^!dV"$&"}
    string3~£""!&vhTT[@
    string4_%^c!}[&(SR#
    string5_$%&<[*^"!"H
    string6_$$£<[*~)!£H

file2:

    @ data1 line1, unique text follows
    data1 line2, unique text follows
    @ data2 line1, unique text follows
    data2 line2, unique text follows
    @ data3 line1, unique text follows
    data3 line2, unique text follows
    @ data4 line1, unique text follows
    data4 line2, unique text follows

Желаемый вывод:

outfile:

    $ data1 line1, unique text follows
    data1 line2, unique text follows
    fixed_text_inserted
    string2-$^^!dV"$&"}
    $ data2 line1, unique text follows
    data2 line2, unique text follows
    fixed_text_inserted
    string6_$$£<[*~)!£H
    $ data3 line1, unique text follows
    data3 line2, unique text follows
    fixed_text_inserted
    string3~£""!&vhTT[@
    $ data4 line1, unique text follows
    data4 line2, unique text follows
    fixed_text_inserted
    string6_$$£<[*~)!£H

fixed_text_inserted всегда одинаков, только строка (без пробелов и табуляции)

Последняя (т.е. 4-я) строка каждой записи - это случайная строка из файла file1 (эти строки содержат специальные символы, например, $ £% "'% ^, и текст, но без пробелов и табуляций).

Случайный выбор с заменой, как в моем примере outfile, где string6 _ $$ £ <[* ~)! £ H} был выбран несколько раз. </p>

У меня около 400 файлов2 и каждый из них большой (~ 1 ГБ), и поэтому мне легко написать слишком медленный сценарий, но у меня возникла проблема с реализацией его с помощью awk.

Вот идея двух команд awk что каждый делает почти половину того, что я хочу:

Сначала получает случайную строку из файла1:

awk 'BEGIN{srand();} {a[NR]=$0} END{for(i=1; i<=5000; i++){x=int(rand()*NR) + 1}}' file 1

Затем используйте эту случайную строку при создании нового файла (outfile) из file2:

awk 'BEGIN {getline rlines; RS = "#" ; FS = "\n"} NR > 1 {print $1"\n"$2"\n"; printf rlines[NR]; printf "\n"}' file2 > outfile

Я сомневаюсь, что объединение этих двух строк - способ сделать это ; эти строки awk предназначены только для того, чтобы дать представление (я надеюсь) о том, что я пытаюсь сделать.

Я публикую это не только потому, что застрял, но и потому, что проблема касается общей проблемы c. как работать с несколькими файлами в awk и как определять сложные переменные в них. Есть примеры в сети, но они рассматривают эти вещи отдельно.

Спасибо всем, у кого есть какие-либо предложения, у меня еще не было ощущения "awk мышления".

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

Звучит так, будто все сводится к замене каждой третьей строки одного файла случайной строкой из второго файла. Это довольно легко сделать с помощью комбинации awk и shuf:

$ cat file1.txt
#a
b
c
#d
e
f
#g
h
i
$ cat file2.txt
1
2
3
4
5
6
$ awk 'NR == FNR { lines[NR]=$0; next }
       { if (FNR % 3) print; else print lines[++i] }' <(shuf file2.txt) file1.txt
#a
b
6
#d
e
2
#g
h
1

Считать перемешанную версию файла строки замены в массив, а затем для каждой третьей строки файла записи: выведите строку замены вместо оригинала.


И для удовольствия, эквивалент bash, который использует копро c для доступа к перемешанным файлам вместо сохранения их в массиве.

#!/usr/bin/env bash
# replace.sh originalfile replacementlinesfile
coproc shuf { shuf "$2"; read; }
declare -i i=1
while IFS= read -r line; do
    if [ $((i++ % 3)) -eq 0 ]; then
        IFS= read -r -u "${shuf[0]}" line
    fi
    echo "$line"
done < "$1"
echo "done" >&"${shuf[1]}"
wait "$shuf_PID"
1 голос
/ 22 апреля 2020

Вставляет случайно выбранную строку из файла1 в файл2 в третьей позиции. Это должно быть очень быстро для этой задачи.

$ sed "3i$(shuf -n1 file1)" file2 > file3

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

$ awk 'BEGIN   {srand()}
       NR==FNR {sub(/[^[:alnum:]].*/,""); a[NR]=$0; size++; next}
       FNR==1  {close(f); f=FILENAME".outfile"} 
               {print > f} 
       !(FNR%2){print a[int(rand()*size)+1] > f}' randomvals file1 file3 ...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...