Bash bc возвращает (standard_in) 1: ошибка синтаксического анализа только тогда, когда часть цикла for

Я перебираю массив целых чисел ${startTimes} (местоположения маркеров в аудиофайле, в сэмплах) и использую bc для преобразования этих целых чисел в миллисекунды. Я передаю результаты в новый массив ${msValuesArray}. Если я запускаю каждый элемент массива по одному, он работает нормально. Если я запускаю его в цикле for:

for i in $(seq 0 ${#startTimes[@]}); do 
    msValuesArray+=($(bc <<< ${startTimes[i]}/44.1))
done

Полученное ${msValuesArray} содержит ожидаемые результаты, но терминал выводит (standard_in) 1: parse error.

Хотя я намереваюсь использовать это в сценарии оболочки, и, прочитав здесь другие вопросы, я узнал, что добавление #!/bin/bash в начало команды позволяет избежать ошибки синтаксического анализа, я до сих пор не понимаю следующее:

а) почему ручная передача элемента ${startTimes} в bc работает без ошибки синтаксического анализа, в то время как цикл for также работает, но выводит ошибку синтаксического анализа (вне сценария оболочки)?

б) несмотря на ошибку синтаксического анализа, у меня есть результирующий массив, который я хочу. Должен ли я игнорировать ошибку?

в) при добавлении #!/bin/bash в начало команд (еще вне шелл-скрипта, просто в командной строке) почему результаты недоступны? (Ввод echo ${msValuesArray[@]} возвращает пустой массив.)

d) При работе внутри сценария оболочки происходит та же ошибка, но просто не печатается на терминал?

Любая помощь приветствуется. Спасибо.


person Urphänomen    schedule 28.08.2017    source источник
comment
Как выглядит массив starts? Имеет ли он то же количество элементов, что и startTimes? Это весь ваш сценарий? Как вы его запускаете? Что вы имеете в виду, добавляя #!/bin/bash в командную строку?   -  person Benjamin W.    schedule 29.08.2017
comment
Извините, неудачная копия/вставка. Я только что исправил это. Должно быть startTimes. У меня еще нет всего сценария, я просто проверяю команды по одной в командной строке, чтобы убедиться, что мой сценарий будет работать (если есть лучший метод, я весь внимание). Для шебанга, если я ввожу все это #!/bin/bash; for...(etc)...; done в командную строку, я не получаю ошибки синтаксического анализа, но также и никаких доступных результатов. Я предполагаю, что он работает в другой оболочке, к которой я не могу получить доступ? Еще учусь, видимо.   -  person Urphänomen    schedule 29.08.2017
comment
И если это поможет, startTimes выглядит так: 0 87053 91463 190062 194472 290520 294930 387582 391992. Просто набор целых чисел.   -  person Urphänomen    schedule 29.08.2017


Ответы (2)


Вы можете перебирать массив напрямую, а не через индексы:

for t in "${startTimes[@]}"; do
    msValuesArray+=($(bc <<< "$t / 44.1"))
done

Это облегчает чтение цикла.

Вы получаете ошибку синтаксического анализа, потому что пытаетесь получить доступ к несуществующему элементу (см. ответ John1024), поэтому bc видит только / 44.1. Вы не должны игнорировать ошибку.

Вы должны указать свою здесь-строку, хотя в данном случае она не вызывает проблем1.

Если вы введете #!/bin/bash просто в командной строке, это не будет иметь никакого эффекта, это просто будет считаться комментарием. Он только что-то делает в качестве первой строки скрипта, а именно указывает, какой интерпретатор следует использовать. Если, как указано в вашем комментарии, вы вводите все это в одну строку как

#!/bin/bash; for ... (etc) ...

вообще ничего не происходит. Это просто комментарий.

Наконец, вы усекаете свои результаты. Если вы хотите, чтобы они были более точными, вы можете установить scale в разумное значение, как в

bc <<< "scale = 3; $t / 44.1"

1 Такие проблемы, как (нежелательное) разделение слов и подстановка. Эта статья представляет собой хороший обзор того, как и зачем цитировать.

person Benjamin W.    schedule 28.08.2017
comment
Спасибо большое! Можете ли вы уточнить важность кавычек для строки здесь? Я все еще не совсем понимаю, как использовать кавычки в целом. - person Urphänomen; 29.08.2017
comment
@Urphänomen Я добавил ссылку на хорошую статью о цитировании. Эмпирическое правило действительно, если вы сомневаетесь, цитируйте. - person Benjamin W.; 29.08.2017
comment
Отлично, спасибо @Benjamin W. Обзор - это то, что мне нужно, очень признателен. - person Urphänomen; 29.08.2017
comment
Решение @Urphänomen Benjamin для for t in "${startTimes[@]}" кажется мне хорошим. Я рекомендую вам принять его ответ. - person John1024; 29.08.2017

У вас проблема с отклонением на 1. Обратите внимание, что с вашим образцом startTimes seq генерирует 10 чисел:

$ startTimes=(0 87053 91463 190062 194472 290520 294930 387582 391992)
$ seq 0 ${#startTimes[@]}
0
1
2
3
4
5
6
7
8
9

Проблема в том, что в startTimes всего 9 записей:

$ declare -p startTimes
declare -a startTimes=([0]="0" [1]="87053" [2]="91463" [3]="190062" [4]="194472" [5]="290520" [6]="294930" [7]="387582" [8]="391992")

Когда i=9, startTimes[9] возвращает пустую строку, что приводит к ошибке bc, которую вы видите:

$ i=9; msValuesArray+=($(bc <<< ${startTimes[i]}/44.1))
(standard_in) 1: syntax error

Или, более прямо:

$ bc <<<"/44.1"
(standard_in) 1: syntax error
person John1024    schedule 28.08.2017
comment
Благодарю вас! Очень полезно. - person Urphänomen; 29.08.2017