Предположим, что я создал файл из 10 строк:
yes "foo bar" | head -n 10 > foobar.txt
[вне]:
foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
И я хочу случайным образом заменить 30% строк пустой строкой, чтобы это выглядело так:
foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
Технически я мог бы написать скрипт на Python для генерации случайных чисел и сделать это ratio-foobar.sh
#!/bin/bash
ratio=$1
numlines=$2
coinflip() {
randnum=$(bc -l <<< $(python -S -c "import random; print(int(random.random() * 100))"))
if [ $randnum -gt $ratio ]
then
return 1
else
return 0
fi
}
for i in $(seq 1 $numlines);
do
if coinflip
then
echo "foo bar"
else
echo ""
fi
done
Использование:
bash ratio-foobar.sh 33 10 > foobar.txt
[вне]:
foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
Но есть ли более простой способ генерировать (возможно, с помощью yes
) определенный процент времени?
Пытался использовать решение @renaud-pacalet, но понял, что весь процесс чтения с плавающей запятой в оболочку — это беспорядок, и каким-то образом bc
снова вмешался. Но почему-то это не сработало:
ratio=$1
lines=$2
ratio=$(echo "scale=3; $ratio/100" | bc)
yes "foo bar" | head -n $2 | awk 'BEGIN {srand()} {print rand() < $ratio ? "" : $0}' > output
cat output
Используйте: bash flip.sh 33 10
для 33% и 10 строк foo bar.
Но когда соотношение жестко запрограммировано, это сработало:
ratio=$1
lines=$2
ratio=$(echo "scale=3; $ratio/100" | bc)
yes "foo bar" | head -n $2 | awk 'BEGIN {srand()} {print rand() < 0.3? "" : $0}' > output
cat output
Есть ли какое-нибудь решение, как считывать проценты и заставить yes | head | awk
работать правильно?
Если python
— это вариант, почему бы вам не использовать только его и не написать сценарий python
(с аргументами, если вы хотите, чтобы он был гибким), который делает все это?
Поскольку вы, очевидно, можете использовать python
, вы можете использовать только это:
from random import randrange as rnd
def foo(n, r, s):
for i in range(n):
print("" if rnd(100) < r else s)
foo(10, 33, "foo bar")
Где n
— количество строк для печати, r
— процент пустых строк и s
— строка для печати. См. модуль argparse
, если вы хотите передать аргументы в скрипт python
.
Вы можете сделать то же самое с любым POSIX awk
(проверено с GNU awk
):
awk -v n=10 -v r=33 -v s = "foo bar" '
END {srand(); for(i=1; i<=n; i++) print rand() < r/100 ? "" : s}' /dev/null
Или с помощью простого bash:
n=10; r=33; s = "foo bar"
for (( i=1; i<=n; i++ )) ; do
(( SRANDOM % 100 < r )) && echo "" || echo "$s"
done
Специальная переменная SRANDOM
преобразуется в 32-битное случайное число. Таким образом, возможно, вы не получите ровно 33%
пустых строк (2 в 32-й степени не кратно 100), но разница должна быть очень маленькой.
Спасибо!! Тогда вся эта bc + python -c
неразбериха исчезнет =)
@alvas Ты не хотел это принимать?
@Renaud-Pacalet каким-то образом я попал в еще одну кроличью нору, пытаясь использовать bc
для чтения чисел с плавающей запятой... Есть ли решение?
Смотрите мой обновленный ответ.
Вы можете получить случайный номер, нажав
$RANDOM
вместо звонкаbc
. stackoverflow.com/questions/1194882/…