#linux #bash #shell
Вопрос:
Я ищу способ случайным образом вставить все строки из одного файла в другой. Уточняя, допустим, у меня есть 2 файла:
toinsert.txt
insert1
insert2
insert3
и
mainfile.txt
line1
line2
line3
line4
line5
...
Результирующий файл должен выглядеть следующим образом, где строки из toinsert.txt
и mainfile.txt
случайным образом перепутаны:
line1
insert1
line2
line3
insert2
...
insert3
...
Есть ли способ легко сделать это в bash? Ваше здоровье!
Комментарии:
1. Должны ли строки сохранять порядок?
2. @KamilCuk Не обязательно, нет. Но на самом деле это помогло бы в этом процессе.
3. Что вы пробовали? Какие исследования вы провели?
4. На самом деле я не эксперт по bash, но я знаком с Python. Это можно легко сделать, прочитав оба файла в 2 разных списка и используя
random.choice()
сzip()
из обоих списков для создания нового списка и записи в файл. Но единственная проблема в том, что я боюсь столкнуться с проблемами с памятью.
Ответ №1:
Вы можете сделать это тривиально , используя shuf
команду вместе с cat
, например
cat toinsert.txt mainfile.txt | shuf
Это позволит объединить строки из toinsert.txt
и mainfile.txt
в перетасованном порядке. Чтобы записать результат обратно mainfile.txt
, вам нужно будет использовать промежуточный временный файл, например
cat toinsert.txt mainfile.txt | shuf > tmp; mov -f tmp mainfile.txt
(конечно, убедитесь, что у вас еще нет tmp
файла, иначе он будет перезаписан)
Дайте мне знать, если у вас возникнут дополнительные вопросы.
Комментарии:
1. Есть ли способ, которым я могу сохранить порядок? Не требуется, просто любопытно.
2. Вы можете, но это было бы немного менее эффективно. Что приходит на ум, так это использование
readarray
для чтения обоих файлов в отдельные массивы, затем вы можете выполнить цикл поmainfile
массиву, чтобы записать случайное количество строк (например0
,1
,2
,…), а затем записать следующую строку изtoinsert
массива. Я уверен, что есть лучший способ сохранить порядок.
Ответ №2:
Вы в основном генерируете 3 случайных числа без повторений в диапазоне количества строк другого файла.
Нравится:
mainfilecnt=$(wc -l <mainfile.txt)
toinsert=$(wc -l <toinsert.txt)
# copy input to output
cp mainfile.txt output.txt
# get as many random numbers as lines to insert in the range of lines
shuf -i 1-"$mainfilecnt" -n "$toinsertcnt" |
sort |
# join numbers with lines
paste - toinsert.txt |
# Reverse to insert from the last line
tac |
# we have number of line to insert to and a line.
# So insert it at that line number.
while IFS=
или как:
# get as many random numbers as lines to insert in the range of lines
shuf -i 1-"$mainfilecnt" -n "$toinsertcnt" |
# sort reverse for inserting
sort -r |
# generate GNU sed script to insert numbers
sed 's/.*/amp;R'toinsert.txt'/' |
# Use xargs to pass generated sed script back to sed
xargs -0 -I{} sed {} mainfile.txt
В приведенных выше сценариях есть ошибка/особенность, из-за которой строка не будет вставлена как первая строка, только как вторая. Это всего лишь очень короткие сценарии, которые я написал, чтобы показать метод - вы должны доработать их для того, что вам действительно нужно.
или как:
t' read -r num line; do
sed -i -e "${num}i"<(printf "%sn" "$line") output.txt
done
В приведенных выше сценариях есть ошибка/особенность, из-за которой строка не будет вставлена как первая строка, только как вторая. Это всего лишь очень короткие сценарии, которые я написал, чтобы показать метод — вы должны доработать их для того, что вам действительно нужно.