一般程序里的局部变量我们都会设置默认值,如果没有传真值,程序执行时候使用默认值,这个在python或其它程序里都比较好实现,在shell里如何实现呢?
test.sh代码
a=1
b=1
echo "\$0 =${0} \$1=${1} \$2=${2}"
echo "default a=${a} b=$b"
echo "update a=${a} b=$b"
即使我们这样执行 bash test.sh --a 10 --b 22, 执行结果
(notebook) root@ai-PowerEdge-R740:/opt/asr/kaldi/egs/lesson/v1/tmp# bash test.sh --a 10 --b 22
$0 =test.sh $1=--a $2=10
default a=1 b=1
update a=1 b=1
我们看到a,b的值并没有更新,如果想要a,b更新应该怎么办呢?
第一种写法是:在原脚本里增加传入参数判断。这个方法虽然也能实现修改参数默认值,但是写法上增加很多行脚本。
a=1
b=1
echo "\$0 =${0} \$1=${1} \$2=${2}"
echo "default a=${a} b=$b"
if [ "$1" == --a ];thena=$2
fi
if [ "$3" == --b ];thenb=$4
fi
echo "update a=${a} b=$b"
运行结果
(notebook) root@ai-PowerEdge-R740:/opt/asr/kaldi/egs/lesson/v1/tmp# bash test.sh --a 10 --b 20
$0 =test.sh $1=--a $2=10
default a=1 b=1
update a=10 b=20
第二种方式:调用kaldi wsj目录下parse_options.sh脚本,这个脚本功能替换第一种方式里判断哪些脚本,而且不用批量改动原脚本里内容, 脚本完整路径 /wsj/s5/utils/parse_options.sh
代码:
a=1
b=1
echo "\$0 =${0} \$1=${1} \$2=${2}"
echo "default a=${a} b=$b"
. ./../utils/parse_options.sh
echo "update a=${a} b=$b"
结果:
(notebook) root@ai-PowerEdge-R740:/opt/asr/kaldi/egs/lesson/v1/tmp# bash test.sh
$0 =test.sh $1= $2=
default a=1 b=1
update a=1 b=1
(notebook) root@ai-PowerEdge-R740:/opt/asr/kaldi/egs/lesson/v1/tmp# bash test.sh --a 10 --b 20
$0 =test.sh $1=--a $2=10
default a=1 b=1
update a=10 b=20
可以看到执行parse_options.sh
完成后,a,b的值已经更新了
下面完整看个示例
demo1.sh
a=1
b=1
. ./../utils/parse_options.sh
echo "a=${a} b=$b"
test.sh
a=10
b=11
echo "default:"
./demo1.sh
echo "update:"
./demo1.sh --a $a --b $b
执行test.sh结果为
(notebook) root@ai-PowerEdge-R740:/opt/asr/kaldi/egs/lesson/v1/tmp# bash test.sh
default:
a=1 b=1
update:
a=10 b=11
可见parse_options.sh只改变当前脚本的参数默认值,写法非常方便。
kaldi里面使用场景, 通常我们在run.sh脚本的全局变量后面使用这个脚本,这样我们运行run.sh时候可以修改全局变量的参数值,如重新指定数据目录,运行控制阶段stage, stop_stage等等这些参数
data=/data/librispeech# base url for downloads.
data_url=www.openslr.org/resources/12
lm_url=https://openslr.magicdatatech.com/resources/11
mfccdir=mfcc
stage=1
stop_stage=1. ./cmd.sh
. ./path.sh
. tools/parse_options.sh
注意:使用这个基本之前如遇到下面报错,则可能使用的shell 是sh, 要改为bash
(base) root@ai-PowerEdge-R740:/opt/asr/kaldi/egs/lesson/v1# sh run.sh --stage 2 --stop_stage 3
run.sh: 34: tools/parse_options.sh: Syntax error: Bad for loop variable
(base) root@ai-PowerEdge-R740:/opt/asr/kaldi/egs/lesson/v1# bash run.sh --stage 2 --stop_stage 3
data/mfcc/train
steps/make_mfcc.sh --cmd run.pl --mem 4G --nj 40 --write-utt2num-frames true --mfcc-config conf/mfcc.conf data/mfcc/train feats/mfcc/log_mfcc_train_data feats/mfcc/feat_train_data
steps/make_mfcc.sh: moving data/mfcc/train/feats.scp to data/mfcc/train/.backup
utils/validate_data_dir.sh: Successfully validated data-directory data/mfcc/train
steps/make_mfcc.sh: [info]: no segments file exists: assuming wav.scp indexed by utterance.
steps/make_mfcc.sh: Succeeded creating MFCC features for train
sid/compute_vad_decision.sh --cmd run.pl --mem 4G --nj 2 data/mfcc/train feats/mfcc/log_vad_train_data feats/mfcc/vad_train_data
sid/compute_vad_decision.sh: moving data/mfcc/train/vad.scp to data/mfcc/train/.backup
Created VAD output for train
fix_data_dir.sh: kept all 400 utterances.
fix_data_dir.sh: old files are kept in data/mfcc/train/.backup