Я решил проблему, понизив llvm-libs и clang до 3.9.0-3 (с 3.9.1-1).
В качестве другого варианта для чтения случайной строки из файла (и присвоения ее переменной) рассмотрим упрощенный метод отбора проб коллектора , преобразованный из реализации perl thrig в awk, с улучшением раздачи Peter.O :
VARIA=$(awk -v seed=$RANDOM 'BEGIN { srand(seed) } { if (rand() * FNR < 1) { line=$0 } } END { print line }' /usr/share/dict/words)
Вот сценарий awk в красивой оболочке:
awk -v seed=$RANDOM '
BEGIN {
srand(seed)
}
{
if (rand() * FNR < 1) {
line=$0
}
}
END {
print line
}' /usr/share/dict/words
Из-за способа awk srand ()
работает, вы получите такое же значение , если вы запустите этот скрипт в течение той же секунды , если только вы не засеваете его чем-то другим случайным; здесь я передал $ RANDOM в bash как семя. Здесь я выбираю слова из / usr / share / dict / words, как источник текста.
Этот метод не заботится о том, сколько строк в файле (моя локальная копия содержит 479 828 строк), поэтому он должен быть довольно гибким.
Чтобы увидеть математические вычисления программы в действии, я написал сценарий оболочки, который выполняет итерацию по различным номерам строк и вероятностям:
#!/bin/sh
for lineno in 1 2 3 4 5 20 100
do
echo "0 .. 0.99999 < ( 1 / FNR == " $(printf 'scale=2\n1 / %d\n' "$lineno" | bc) ")"
for r in 0 0.01 0.25 0.5 0.99
do
result=$(printf '%f * %d\n' "$r" "$lineno" | bc)
case $result in
(0*|\.*) echo "Line $lineno: Result of probability $r * line $lineno is $result and is < 1, choosing line" ;;
(*) echo "Line $lineno: Result of probability $r * line $lineno is $result and is >= 1, not choosing line" ;;
esac
done
echo
done
Результаты:
0 .. 0.99999 < ( 1 / FNR == 1.00 )
Line 1: Result of probability 0 * line 1 is 0 and is < 1, choosing line
Line 1: Result of probability 0.01 * line 1 is .010000 and is < 1, choosing line
Line 1: Result of probability 0.25 * line 1 is .250000 and is < 1, choosing line
Line 1: Result of probability 0.5 * line 1 is .500000 and is < 1, choosing line
Line 1: Result of probability 0.99 * line 1 is .990000 and is < 1, choosing line
0 .. 0.99999 < ( 1 / FNR == .50 )
Line 2: Result of probability 0 * line 2 is 0 and is < 1, choosing line
Line 2: Result of probability 0.01 * line 2 is .020000 and is < 1, choosing line
Line 2: Result of probability 0.25 * line 2 is .500000 and is < 1, choosing line
Line 2: Result of probability 0.5 * line 2 is 1.000000 and is >= 1, not choosing line
Line 2: Result of probability 0.99 * line 2 is 1.980000 and is >= 1, not choosing line
0 .. 0.99999 < ( 1 / FNR == .33 )
Line 3: Result of probability 0 * line 3 is 0 and is < 1, choosing line
Line 3: Result of probability 0.01 * line 3 is .030000 and is < 1, choosing line
Line 3: Result of probability 0.25 * line 3 is .750000 and is < 1, choosing line
Line 3: Result of probability 0.5 * line 3 is 1.500000 and is >= 1, not choosing line
Line 3: Result of probability 0.99 * line 3 is 2.970000 and is >= 1, not choosing line
0 .. 0.99999 < ( 1 / FNR == .25 )
Line 4: Result of probability 0 * line 4 is 0 and is < 1, choosing line
Line 4: Result of probability 0.01 * line 4 is .040000 and is < 1, choosing line
Line 4: Result of probability 0.25 * line 4 is 1.000000 and is >= 1, not choosing line
Line 4: Result of probability 0.5 * line 4 is 2.000000 and is >= 1, not choosing line
Line 4: Result of probability 0.99 * line 4 is 3.960000 and is >= 1, not choosing line
0 .. 0.99999 < ( 1 / FNR == .20 )
Line 5: Result of probability 0 * line 5 is 0 and is < 1, choosing line
Line 5: Result of probability 0.01 * line 5 is .050000 and is < 1, choosing line
Line 5: Result of probability 0.25 * line 5 is 1.250000 and is >= 1, not choosing line
Line 5: Result of probability 0.5 * line 5 is 2.500000 and is >= 1, not choosing line
Line 5: Result of probability 0.99 * line 5 is 4.950000 and is >= 1, not choosing line
0 .. 0.99999 < ( 1 / FNR == .05 )
Line 20: Result of probability 0 * line 20 is 0 and is < 1, choosing line
Line 20: Result of probability 0.01 * line 20 is .200000 and is < 1, choosing line
Line 20: Result of probability 0.25 * line 20 is 5.000000 and is >= 1, not choosing line
Line 20: Result of probability 0.5 * line 20 is 10.000000 and is >= 1, not choosing line
Line 20: Result of probability 0.99 * line 20 is 19.800000 and is >= 1, not choosing line
0 .. 0.99999 < ( 1 / FNR == .01 )
Line 100: Result of probability 0 * line 100 is 0 and is < 1, choosing line
Line 100: Result of probability 0.01 * line 100 is 1.000000 and is >= 1, not choosing line
Line 100: Result of probability 0.25 * line 100 is 25.000000 and is >= 1, not choosing line
Line 100: Result of probability 0.5 * line 100 is 50.000000 and is >= 1, not choosing line
Line 100: Result of probability 0.99 * line 100 is 99.000000 and is >= 1, not choosing line
Исходная формула:
rand() * FNR < 1
может математически переписать как:
rand() < 1 / FNR
... что более интуитивно для меня, так как демонстрирует уменьшение значений в правой части по мере увеличения номеров строк. По мере того, как значения в правой части уравнения уменьшаются, вероятность того, что функция rand () вернет значение, меньшее, чем правая часть, уменьшается.
Для каждого номера строки я печатаю представление формулы, которая будет проверяться: диапазон вывода функции rand () и «1, разделенная на номер строки».Затем я перебираю несколько выборочных случайных значений, чтобы увидеть, будет ли выбрана линия с учетом этого случайного значения.
Интересно рассмотреть несколько примеров:
просто используйте эту команду
VARIA=$(head -n "$((${RANDOM} % $(wc -l < test) + 1))" test | tail -n 1)
для присвоения результата команды переменной мы используем $(...)
(древнюю форму `...`
сложнее вложить).
Он не работает, потому что вы пытаетесь вложить незачеркнутые обратные символы:
VARIA=`head -$((${RANDOM} % `wc -l < file` + 1)) file | tail -1`
На самом деле он пытается сначала выполнить head -$((${RANDOM} %
как одну команду, и это дает вам 2 первые ошибки:
$ VARIA=`head -$((${RANDOM} % `
bash: command substitution: line 1: unexpected EOF while looking for matching `)'
bash: command substitution: line 2: syntax error: unexpected end of file
Затем он пытается выполнить
wc -l < file` + 1)) file | tail -1`
Что означает, что он пытается оценить + 1)) file | tail -1
(который находится между обратными знаками), и это дает следующие ошибки:
$ wc -l < file` + 1)) file | tail -1`
bash: command substitution: line 1: syntax error near unexpected token `)'
bash: command substitution: line 1: ` + 1)) file | tail -1'
Вы можете обойти это, экранируя обратные знаки:
VARIA=`head -$((${RANDOM} % \`wc -l < file\` + 1)) file | tail -1`
Однако, как правило, лучше не использовать обратные знаки вообще. Вместо них почти всегда следует использовать $()
. Они более надежны и могут быть вложены бесконечно, а их синтаксис проще:
VARIA=$(head -$((${RANDOM} % $(wc -l < file) + 1)) file | tail -1)