Есть ли лучший способ получить том MacOS в виде целочисленного значения? (Bash) - PullRequest
0 голосов
/ 22 января 2020

Я пытаюсь получить целочисленное значение выходного тома MacOS для использования в виджете Übersicht, и у меня есть рабочее (но грязное) решение. Проблема в том, что значение сохраняется в процентах, округленное до ближайшего целого числа. Я подумал об использовании линейной регрессии, чтобы получить функцию, которая возвращала бы значение 1-64, но десятичные дроби ... не вещь в bash. Мне также нужно сделать это в одной строке, что способствует общей путанице в коде. В любом случае, это мой текущий код:

vol=$(osascript -e 'get volume settings' | cut -f2 -d':' | cut -f1 -d','); [ \"$vol\" = \"2\" ] &&let vol=1; [ \"$vol\" = \"3\" ] &&let vol=2; [ \"$vol\" = \"5\" ] &&let vol=3; [ \"$vol\" = \"6\" ] &&let vol=4; [ \"$vol\" = \"8\" ] &&let vol=5; [ \"$vol\" = \"9\" ] &&let vol=6; [ \"$vol\" = \"11\" ] &&let vol=7; [ \"$vol\" = \"13\" ] &&let vol=8; [ \"$vol\" = \"14\" ] &&let vol=9; [ \"$vol\" = \"16\" ] &&let vol=10; [ \"$vol\" = \"17\" ] &&let vol=11; [ \"$vol\" = \"19\" ] &&let vol=12; [ \"$vol\" = \"20\" ] &&let vol=13; [ \"$vol\" = \"22\" ] &&let vol=14; [ \"$vol\" = \"23\" ] &&let vol=15; [ \"$vol\" = \"25\" ] &&let vol=16; [ \"$vol\" = \"26\" ] &&let vol=17; [ \"$vol\" = \"28\" ] &&let vol=18; [ \"$vol\" = \"30\" ] &&let vol=19; [ \"$vol\" = \"31\" ] &&let vol=20; [ \"$vol\" = \"33\" ] &&let vol=21; [ \"$vol\" = \"34\" ] &&let vol=22; [ \"$vol\" = \"36\" ] &&let vol=23; [ \"$vol\" = \"38\" ] &&let vol=24; [ \"$vol\" = \"39\" ] &&let vol=25; [ \"$vol\" = \"41\" ] &&let vol=26; [ \"$vol\" = \"42\" ] &&let vol=27; [ \"$vol\" = \"44\" ] &&let vol=28; [ \"$vol\" = \"45\" ] &&let vol=29; [ \"$vol\" = \"47\" ] &&let vol=30; [ \"$vol\" = \"48\" ] &&let vol=31; [ \"$vol\" = \"50\" ] &&let vol=32; [ \"$vol\" = \"51\" ] &&let vol=33; [ \"$vol\" = \"54\" ] &&let vol=34; [ \"$vol\" = \"55\" ] &&let vol=35; [ \"$vol\" = \"56\" ] &&let vol=36; [ \"$vol\" = \"58\" ] &&let vol=37; [ \"$vol\" = \"60\" ] &&let vol=38; [ \"$vol\" = \"61\" ] &&let vol=39; [ \"$vol\" = \"62\" ] &&let vol=40; [ \"$vol\" = \"65\" ] &&let vol=41; [ \"$vol\" = \"66\" ] &&let vol=42; [ \"$vol\" = \"67\" ] &&let vol=43; [ \"$vol\" = \"68\" ] &&let vol=44; [ \"$vol\" = \"70\" ] &&let vol=45; [ \"$vol\" = \"72\" ] &&let vol=46; [ \"$vol\" = \"74\" ] &&let vol=47; [ \"$vol\" = \"75\" ] &&let vol=48; [ \"$vol\" = \"76\" ] &&let vol=49; [ \"$vol\" = \"78\" ] &&let vol=50; [ \"$vol\" = \"79\" ] &&let vol=51; [ \"$vol\" = \"81\" ] &&let vol=52; [ \"$vol\" = \"83\" ] &&let vol=53; [ \"$vol\" = \"85\" ] &&let vol=54; [ \"$vol\" = \"86\" ] &&let vol=55; [ \"$vol\" = \"88\" ] &&let vol=56; [ \"$vol\" = \"89\" ] &&let vol=57; [ \"$vol\" = \"91\" ] &&let vol=58; [ \"$vol\" = \"92\" ] &&let vol=59; [ \"$vol\" = \"94\" ] &&let vol=60; [ \"$vol\" = \"95\" ] &&let vol=61; [ \"$vol\" = \"97\" ] &&let vol=62; [ \"$vol\" = \"98\" ] &&let vol=63; [ \"$vol\" = \"100\" ] &&let vol=64; mute=$(osascript -e 'get volume settings' | cut -f2 -d'd' | cut -f2 -d':'); [ \"$mute\" = \"true\" ] &&let vol=0; echo $vol

По сути, я просто получаю значение, преобразовываю его в число 1-64, устанавливаю это значение в ноль, если система отключена, и возвращаю это значение. Идеи? Я очень новичок в bash, поэтому, пожалуйста, извините за мое явное отсутствие базовых c знаний!

Ответы [ 2 ]

1 голос
/ 22 января 2020

TL; DR : awk - король, просто используйте awk:

osascript -e 'get volume settings' | awk '-F:|,' '/true/ { print 0; exit; } { print int($2 / (100 / 64)) }' 

Вот некоторые из старых вещей, которые я пробовал, прежде чем Чарльз Даффи показал свою силу уровень:

Десятичные дроби могут быть в bash, вам просто нужен инструмент. Как отмечается в комментариях, awk действительно хорош в таких вещах:

osascript -e 'get volume settings' | awk '-F:|,' '{print int($2 / (100 / 64))}'

Наконец, вы можете просто проверить, есть ли в строке true или false, и сбросить громкость на основе что:

# if we see "true" in the string, we're muted and should set volume to 0
osascript -e 'get volume settings' | grep "true" &>/dev/null && vol=0;

Собрав все это вместе, мы получим

osascript -e 'get volume settings' | awk '-F:|,' '{print int($2 / (100 / 64))}';
osascript -e 'get volume settings' | grep "true" &>/dev/null && vol=0;
echo "$vol"

Вы всегда можете сложить их вместе в одну строку, если это необходимо.

Вы можете сделать это еще короче за счет читабельности или дольше и сохраните вызов на osascript, чтобы вы звонили только один раз.

0 голосов
/ 30 января 2020

Если, как вы сказали, вам нужен только выходной объем, вам не нужен awk. Если вам не нужна математическая точность, когда дело доходит до округления нецелого десятичного числа до целого числа, вы можете использовать это:

osascript <<< "(output volume of (get volume settings) * 0.64) as integer"

Примечательно, что это занимает от 0,5 до 0 и от 2,5 до 2, но большинство другие половины ведут себя нормально (это связано с внутренними ошибками с плавающей запятой).

Если вы сохраните точность sh, то вы можете использовать это:

osascript <<< "round ((output volume of (get volume settings)) * 0.64) rounding as taught in school"

Это округлит вверх или вниз так, как можно (или нужно) на экзамене по математике.

Обведите все это vol=$( ... ) для назначения переменной, заменив три точки одним из двух приведенных выше выражений.


Приглушено / Не приглушено

Использование второго из двух приведенных выше примеров для демонстрации способа присвоения значения 0 переменной bash vol, если звук отключен, имеет вид это:

vol=$(( $(osascript <<< "tell (get volume settings) to ¬
    if not output muted then tell (output volume * 0.64) ¬
    to continue round it rounding as taught in school") ))

Я разбил AppleScript на несколько строк для удобства чтения, которые вы можете оставить как есть, или удалите символы продолжения (¬) и поместите его в одну строку, если это что вам нужно.

T он использует bash арифметическую расшифровку c, $(( ... )), внутри которой находится вызов osascript, который теперь условно возвращает значение output volume , если и только если системный том не отключен.

Если системный том отключен , сценарий ничего не возвращает, то есть пустое выражение - которое, bash арифметическое c выражение просто так оценивается как 0.

Просто, если вы заинтересованы ...

Есть несколько других способов использовать bash арифметических c выражений для достижения аналогичного эффекта:

  • Вы можете переместить все назначение внутри арифметического c расширения:

    (( vol=$(osascript <<< "tell (get volume settings) to ¬
        if not output muted then tell (output volume * 0.64) ¬
        to continue round it rounding as taught in school")+0 ))
    

    В этой ситуации мы должны добавить 0 к выражению: это потому, что один из возможных результатов AppleScript - ничего не возвращать, что привело бы к бессмысленному математическому выражению, а именно (( vol= )). Тем не менее, (( vol=+0 )) абсолютно нормально и не меняет значение результата, когда AppleScript возвращает число.

    Эта синтаксическая форма может быть полезна, потому что будет отключен системный том или нет. отражается в состоянии возврата этой строки кода bash, т. е. если системный том отключен, состояние возврата отличное от нуля.

  • Другой способ оценки арифметики c выражения bash должны использовать let. Поскольку присвоение переменной происходит как часть самого выражения арифметического c, также потребуется добавить 0, чтобы обеспечить полный и действительный расчет во всех сценариях ios:

    let vol=$(osascript <<< "tell (get volume settings) to ¬
        if not output muted then tell (output volume * 0.64) ¬
        to continue round it rounding as taught in school")+0
    

    И, опять же, состояние возврата будет ненулевым, если громкость системы отключена (обратите внимание, что это не означает, что значение vol будет отличным от нуля; фактически оно обязательно будет нулевым).

Если статус возврата не тот, который вы будете использовать, то все эти три формы практически одинаковы, и ни одна из них не дает каких-либо определенных c преимуществ или недостатков по сравнению с два других (если только один из них не находит конкретный синтаксис более зрительным).

Я специально не использовал bc для оценки этих арифметических c выражений. bc - это основная математическая программа, наиболее часто используемая в bash, особенно при выполнении арифметических операций с плавающей запятой c. Тем не менее, главная тема моего решения заключается в том, чтобы сделать решение как можно более простым и не полагаться на цепочку конвейеров во внешние программы в ситуациях, когда это не нужно, а также менее эффективно, чем использовать преимущества, которые способен bash делать изначально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...