В первый раз в вашем цикле вы устанавливаете energy=( $(awk...) )
, и вывод из awk
состоит из нескольких строк, каждая из которых содержит одно число и заканчивается символом новой строки, как это всегда делают строки в Unix. Подстановка команд $(... )
удаляет завершающую новую строку (с ), а когда она не заключена в двойные -кавычки, то разбивает результат на «слова» в любой из пробелов на новой строке (у вас есть новые строки ), и, наконец, если какое-либо слово является «шаблоном» (, содержащим ?*[..]
), которое соответствует любому имени файла (s ), оно заменяется этими именами файлов (s )как отдельные «слова» (у вас нет таких шаблонов 'glob' ). Назначение массива energy=(... )
затем сохраняет эти слова как элементы массива.
Во второй раз через IFS устанавливается запятая. Теперь, когда $(... )
пытается разбить на слова, он использует (только запятую )и в выводе awk нет запятых, поэтому весь вывод (, включая новые строки ), остается как одно слово и присваивается массиву как один элемент.
Вам необходимо возвращать IFS для каждой итерации. Кроме того, вам необходимо установить стандартное значение IFS или, по крайней мере, значение, содержащее новую строку, в записи этого скрипта. OTOH откат IFS непосредственно перед выходом из скрипта в основном бесполезен; сценарий обычно запускается в отдельном процессе оболочки, и любые настройки переменных или другие изменения процесса -, сделанные сценарием, отбрасываются при выходе из сценария.
Или , вместо изменения IFS и явного возврата, вы можете сделать это в подоболочке , чтобы изменение отбрасывалось после завершения подоболочки. Синтаксис оболочки для подоболочки: также круглые скобки, на этот раз сами по себе:
( IFS=","; echo "${energy[*]};" >> $energies )
# you don't actually need to quote, here but
# it's a good habit for string literals in general
Также в целом printf
безопаснее, чем echo
, потому что в зависимости от используемой оболочки и/или системы echo
может исказить некоторые строковые значения. Однако значения, которые вы здесь --ограничены десятичными числами --, безопасны для echo
.
Для bash есть еще одна возможность обрабатывать данные как одну строку, а не как массив:
energy=$( awk '/Total energy/{print $3}' output )
# command substitution strips the last newline
# scalar assignment does NOT do wordsplit and glob
echo "${energy//$'\n'/,};" >>energies_blah
# replaces all other newlines with commas, and adds semicolon
echo "${energy##*$'\n'}" >>final_energies_blah
# removes everything up to and including the last newline,
# leaving only the last number
Или вы можете выполнять всю работу с помощью awk, особенно не -древнего GNU awk с 'endfile':
# read simcount,simend and set energies,fenergies
infiles=$( printf 'sim%d/output ' $( seq $simcount $simend ) )
awk -vf1=$energies -vf2=$fenergies '/Total Energy/ {e=e","$3; f=$3} ENDFILE {print substr(e,2)";">>f1; print f>>f2; e=f=""}' $infiles
С другими awk вы можете сделать то же самое с немного более уродливым кодом (сначала! )проверка FNR==1&&NR>1
конца каждого файла, кроме последнего, и (где угодно)END
конца последнего файла.
С помощью команд arecord
и sox
вы можете записать выборку единиц и измерить ее уровень:
arecord -qd 1 file && sox file -n stat
Вот пример вывода:
Samples read: 8000
Length (seconds): 1.000000
Scaled by: 2147483647.0
Maximum amplitude: 0.992188
Minimum amplitude: -0.992188
Midline amplitude: 0.000000
Mean norm: 0.093221
Mean amplitude: -0.015338
RMS amplitude: 0.232947
Maximum delta: 0.617188
Minimum delta: 0.000000
Mean delta: 0.001067
RMS delta: 0.009643
Rough frequency: 52
Volume adjustment: 1.008
Если вас интересует только уровень/максимальная амплитуда, вы можете передать результат в awk
для вывода только второго поля четвертой строки:
arecord -qd 1 /tmp/rec.waw && sox /tmp/rec.waw -n stat 2>&1 | awk 'BEGIN{FS=":"} NR==4 {print $2}'
И если вы хотите отслеживать его эволюцию, вы можете поместить эту команду в цикл while:
while :; do
arecord -qd 1 /tmp/rec.waw && sox /tmp/rec.waw -n stat 2>&1 | awk 'BEGIN{FS=":"} NR==4 {print $2}'
sleep 1 # repeat every one second
done
Выход:
0.992188
0.023438
0.046875
0.375000
0.523438
0.109375
0.242188
Если вы хотите, чтобы выходной сигнал был в дБ, вы можете рассчитать его с помощьюawk
:
while :; do
arecord -qd 1 /tmp/rec.waw && sox /tmp/rec.waw -n stat 2>&1 | awk 'BEGIN{FS=":"} NR==4 {db=20*log($2)/log(10); printf("%0.4f\n",db}'
sleep 1 # repeat every one second
done
Выход в дБ:
-12.6467
-13.4366
-13.2010
-14.4959
Вы можете использовать sox
. Пример с Pulseaudio и моей веб-камерой в качестве источника:
sox -S -t pulseaudio alsa_input.usb-046d_0809_23E942AD-02.analog-mono -n stats
Также работает с устройствами ALSA, вы можете указать устройство по умолчанию и т. д. Подробнее см. man sox
. Используйте pactl list short sources
для получения списка источников Pulseaudio.