Linux用のシェルスクリプトをBashを使用して作成し、ビデオファイルをMP4に変換します。そのため、私はavconv
をlibvorbis
とともにオーディオに使用しています。
スクリプト内で、ユーザーに質問があります。
read -p "- Audio Quality [scale from -2 to 10] ? "
if [ -n "$REPLY" ] ; then
ABITRATE="-aq $REPLY"
fi
私の "ABITRATE"文字列は最後のavconv
コマンドラインに入ります。
しかし、Kb(Kilobit))の値でその質問に答え、libvorbis
が使用するスケールに変換する機会をユーザーに提供したいと思います。 -2から10 "はこれです:
Quality Kbit/s Normalization
-----------------------------
-2 ~32 y
-1 ~48 y
0 ~64 y
1 ~80 y
2 ~96 y
3 ~112 y
4 ~128 n
5 ~160 n
6 ~192 n
7 ~224 n
8 ~256 n
9 ~320 n
10 ~500 n
$ REPLYが範囲内かどうかを確認する方法を教えてください。たとえば、スクリプトで次のような処理を実行したいとします。
if [ $REPLY is a number between 1 and 32 ] ; then
REPLY="-2"
Elif [ $REPLY is a number between 33 and 48 ] ; then
REPLY="-1"
fi
これは可能ですか(「もちろん、難しいことではありません」と言っても構わないが、使用する構文がわからない)。
[
コマンド/ Shellビルトインには比較テストがあるので、あなたはただ行うことができます
if [ "$REPLY" -ge 1 ] && [ "$REPLY" -le 32 ]; then REPLY=-2;
Elif [ "$REPLY" -ge 33 ] && [ "$REPLY" -le 48 ]; then REPLY=-1; fi
ここで、-ge
は「以上」を意味します(以下同様)。 [
コマンドは単なるコマンドであり、特別な構文ではありません(実際にはtest
と同じです。man test
をチェックアウトしてください)。そのため、スペースが必要です。 [$REPLY
と書くと、[$REPLY
という名前のコマンドを見つけて実行しようとしますが、機能しません。 ]
を閉じる場合も同様です。
ここでは、&&
シェル演算子を使用して、最初のコマンドが成功した場合にのみ2番目のコマンドを実行しています。 [
は-a
to and 2つのテストもサポートしていますが、非推奨であり、引数を確実に解析できないため、その使用はお勧めできません。
編集:数値が整数かどうかをテストするには(それがコードで発生する可能性がある場合)、最初にテストを実行します
if [[ "$REPLY" =~ ^[0-9]+$ ]]; then
existing code
else echo "$REPLY is not an integer" >&2 && exit 1; fi
もちろん、これらのブラケット式はすべて0(true)または1(false)を返し、組み合わせることができます。すべてを同じブラケットに入れることができるだけでなく、
if [[ "$REPLY" =~ ^[0-9]+$ ]] && [ "$REPLY" -ge 1 ] && [ "$REPLY" -le 32 ]; then ...
または似たようなもの。
あなたはこのようなことをすることができます:
#!/usr/bin/env bash
read -p "- Audio Quality [scale from -2 to 10] ? "
if [ -n "$REPLY" ] ; then
ABITRATE="-aq $REPLY"
fi
echo "You chose : $ABITRATE : $REPLY"
## If 0 < $REPLY < 33 and $REPLY is a number
if [[ "$REPLY" =~ ^[0-9]+$ && "$REPLY" -gt 0 && "$REPLY" -lt 33 ]]
then
echo "GOOD"
else
echo "BAD"
fi
まず、入力が数値かどうかをテストします。たとえば、 bash条件式 の正規表現一致演算子を使用します。
if [[ $REPLY =~ -?[0-9]+ ]]; then
echo "Invalid input (not numeric): $REPLY"
exit 2
fi
数値範囲をテストするには、2つの可能性があります。
-gt
または[ … ]
内の 条件式 の[[ … ]]
演算子(<
および>
演算子は文字列比較を行うことに注意してください。数値比較なので、[[ 10 < 9 ]]
はtrueです);((…))
内の通常の arithmetic 演算子。したがって:
if ((REPLY >= -2 && REPLY <= 10)); then
: # do nothing -- pass directly to libvorbis
Elif ((REPLY <= 24)); then
echo "Value outside supported range: $REPLY"
exit 2
Elif ((REPLY <= 135)); then
REPLY=$(((REPLY+8) / 16 - 4))
Elif ((REPLY <= 271)); then
REPLY=$(((REPLY+16) / 32))
Elif ((REPLY <= 400)); then
REPLY=9
Elif ((REPLY <= 707)); then
REPLY=10
else
echo "Value outside supported range: $REPLY"
exit 2
fi
(別の近似ルールを使用することもできますが、ここで選択したものが最適かどうかはわかりません。)
文字列が(10進数)番号であるかどうかを正しく検出するには、最初に10進数の整数を定義する必要があります。シンプルかつ完全な定義は次のとおりです。
オプションの符号(+または-)とそれに続く18(有効)以下の10進数字のシーケンス。
そして、このステップが必要です:
正規表現が1つあれば、そのほとんどを実行できます。
re='^([+-])?0*([0-9]{1,18})$'
[[ $number =~ $re ]] && integer=${BASH_REMATCH[*]:1}
複数の数値を処理するコードは次のとおりです。
#!/bin/bash
DebugLevel=4 # 1:fatal 2:error 3:warn 4:info 5:debug 6:trace
SayMsg (){ local a; a=$1; shift ; # Log level
[[ $a -le $DebugLevel ]] && printf '%s' "$@" $'\n' >&2 ;
}
SayError (){ a=$1; shift; printf '%s' "$@" $'\n' >&2; exit "$a"; }
parseint (){ local re # Parse the first argument as an integer or fail
re='^([+-])?0*([0-9]{1,18})$'
[[ $1 =~ $re ]] || { SayMsg 4 "Invalid number $1"; return 2; }
integer=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
echo "integer=$integer"
}
while read val; do
parseint "$val"
done <<-\_EOT_
0
1
10
100
2345
123456789012345678
923456789012345678
999999999999999999
0000000012345
+023
-00045
-76
""
''
a
abc
1234567890123456789
7.23
-8.17
1e3
10+11
_EOT_
どちらが印刷されます:
integer=0
integer=1
integer=10
integer=100
integer=2345
integer=123456789012345678
integer=923456789012345678
integer=999999999999999999
integer=12345
integer=+23
integer=-45
integer=-76
Invalid number ""
Invalid number ''
Invalid number
Invalid number a
Invalid number abc
Invalid number 1234567890123456789
Invalid number 7.23
Invalid number -8.17
Invalid number 1e3
Invalid number 10+11
数値が明確になったら、欠けている唯一のテストは値の範囲を制限することです。この簡単な数行で、次のようになります。
(( 1 <= integer && integer <= 32 )) && REPLY="-2"
(( 33 <= integer && integer <= 48 )) && REPLY="-1"