一、Shell 參數(shù)獲取的兩種方式
方式一
示例
新建一個test.sh文件
#!/bin/bash
echo "shell 名稱 = $0"
echo "參數(shù)1 = $1"
echo "參數(shù)2 = $2"
echo "參數(shù)3 = $3"
echo "參數(shù)4 = $4"
echo "參數(shù)5 = $5"
執(zhí)行腳本 : sh test.sh 5 6 3 6 2
-
輸出的結(jié)果:
-
shell 名稱 = test.sh 參數(shù)1 = 5 參數(shù)2 = 6 參數(shù)3 = 3 參數(shù)4 = 6 參數(shù)5 = 2
-
使用該方式有兩點(diǎn)需要注意的地方:“$0” 表示的是腳本名稱本身
- 優(yōu)點(diǎn) : 獲取參數(shù)方便、簡潔
- 缺點(diǎn) :必須按照指定的順序輸入?yún)?shù),中間不能漏參數(shù)。否則參數(shù)將會產(chǎn)生錯亂。
方式二 使用 getopts 方式獲取
-
如果需要實(shí)現(xiàn)類似 job_3.sh -f -d 指定參數(shù)值的方式,則推薦使用此種方式。
使用該方式需要使用到Shell內(nèi)置的函數(shù)"getopts"。
在使用之前你需要知道一下幾個內(nèi)置參數(shù)的意義:
1.optstring option :字符串,當(dāng)中為參數(shù)選項(xiàng),會逐個匹配。
2.varname :每次匹配成功的選項(xiàng)
3.arg :參數(shù)值
4.$OPTIND :option index,會逐個遞增,初始值為1
5.$OPTARG :option argument,不同情況下會有不同的值
該函數(shù)的具體使用方式 : getopts [option[:]] VARIABLE
參數(shù)說明:
- [option[:]] 表示參數(shù),以"??b:c:"的方式設(shè)置
#####注意細(xì)節(jié):
- 以":"開頭時:getopts不會提示錯誤信息,會區(qū)分invalid option錯誤和miss option argument,兩種錯誤的值不一樣。invalid option錯誤時,VARIABLE會被設(shè)為*?。為出問題的option。miss option argument時,VARIABLE會被設(shè)為*。$OPTARG為出問題的option。
- 不以":"開頭時:getopts會提示錯誤信息。會根據(jù)invalid option錯誤和miss option argument。提示兩種不同的錯誤。VARIABLE都會被設(shè)為?。$OPTARG都為空。
- 如果option后面跟了":"表示該option可以接收參數(shù),參數(shù)(argument)會被放在$OPTARG中。
示例getopt.sh
#!/bin/bash
while getopts ":a:p:n:s:" opt
do
case $opt in
n)
echo "$OPTARG"
;;
s)
echo "$OPTARG"
;;
a)
echo "$OPTARG"
;;
p)
echo "$OPTARG"
;;
*)
echo "未知參數(shù)$opt"
echo "參數(shù)值$OPTARG"
;;
?)
echo "未知參數(shù)$opt"
echo "參數(shù)值$OPTARG"
;;
esac
done
-
執(zhí)行:sh getopt.sh -a 12 -p 32 -s string -n 你好 -r 世界
-
輸出:
12
32
string
你好
install.sh: 非法選項(xiàng) -- r
未知參數(shù)?
參數(shù)值
可選參數(shù)示例
- 腳本可以傳1到多個參數(shù)該如何處理?如下面例子:
#!/bin/bash
readonly CURR=$(readlink -m $(dirname $0))
#
path=`sed -n '/^\[path/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config | sed 's/[ \t]//g' `
file=` sed -n '/^\[file/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config | sed 's/[ \t]//g' `
date='date -d yesterday + '%Y%m%d'`
#/cib/etl_job
app_path=` sed -n '/^\[app_path/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config | sed 's/[ \t]//g' `
today=`date + %Y%m%d`
show_usage=" args:[ -p,-f,-d,-h] [--path, --file, --date, --help]"
GETOPT_ARGS=`getopt -o p:f:d:h -al path:file:date:qhlep --"$@"`
eval set -- "$GETOPT_ARGS"
while [ -n "$1" ]
do
case "$1" in
-p|--path) test -z $2 || path=$2; shift 2;;
-f|--file) test -z $2 || file=$2; shift 2;;
-d|--date) test -z $2 || date=$2; shift 2;;
-h|--help)cat $CURR/../conf/readme1 && exit 0; shift 2;;
--) break;;
*) echo $1 , $2; shift 1;;
esac
done
這段Shell代碼是一個使用getopt
解析命令行參數(shù)的示例。
代碼解釋如下:
-
GETOPT_ARGS=$(getopt -o p:f:d:h -al path:file:date:help -- "$@")
- 使用
getopt
命令解析命令行參數(shù),并將結(jié)果保存到GETOPT_ARGS
變量中。 -
-o
后面跟短選項(xiàng),例如p:f:d:h
表示短選項(xiàng)為-p
、-f
、-d
和-h
。 -
-l
后面跟長選項(xiàng),例如path:file:date:help
表示長選項(xiàng)為--path
、--file
、--date
和--help
。 -
--
表示選項(xiàng)結(jié)束,之后的參數(shù)將被視為位置參數(shù)。 -
"$@"
表示將腳本接收到的所有參數(shù)傳遞給getopt
命令。
- 使用
-
eval set -- "$GETOPT_ARGS"
- 將
GETOPT_ARGS
的值設(shè)置為新的參數(shù)列表,相當(dāng)于重置了腳本中的位置參數(shù)。這樣,后續(xù)的$1
、$2
等就可以用于處理解析后的命令行參數(shù)。
- 將
-
while [ -n "$1" ]
- 這是一個循環(huán)語句,用于逐個處理命令行參數(shù),直到所有參數(shù)都被處理完畢。
-
case "$1" in ... esac
- 這是一個條件判斷語句,根據(jù)當(dāng)前參數(shù)的值執(zhí)行相應(yīng)的操作。
-
-p | --path) test -z $2 || path=$2; shift 2;;
- 當(dāng)參數(shù)是
-p
或--path
時,將下一個參數(shù)(即$2
)賦值給path
變量,并通過shift 2
將已處理的兩個位置參數(shù)移除。
- 當(dāng)參數(shù)是
-
-f | --file) test -z $2 || file=$2; shift 2;;
- 當(dāng)參數(shù)是
-f
或--file
時,將下一個參數(shù)(即$2
)賦值給file
變量,并通過shift 2
將已處理的兩個位置參數(shù)移除。
- 當(dāng)參數(shù)是
-
-d | --date) test -z $2 || date=$2; shift 2;;
- 當(dāng)參數(shù)是
-d
或--date
時,將下一個參數(shù)(即$2
)賦值給date
變量,并通過shift 2
將已處理的兩個位置參數(shù)移除。
- 當(dāng)參數(shù)是
-
-h | --help) cat $CURR/../conf/readme1 && exit 0; shift 2;;
- 當(dāng)參數(shù)是
-h
或--help
時,打印readme1
文件的內(nèi)容并退出腳本。
- 當(dāng)參數(shù)是
-
--) break;;
- 當(dāng)遇到
--
標(biāo)記時,停止循環(huán)。
- 當(dāng)遇到
-
*) echo $1 , $2; shift 1;;
- 對于其他未匹配的參數(shù),打印參數(shù)的值,并通過
shift 1
將已處理的一個位置參數(shù)移除。
- 對于其他未匹配的參數(shù),打印參數(shù)的值,并通過
通過以上步驟,腳本會逐個處理命令行參數(shù),并根據(jù)參數(shù)的類型進(jìn)行相應(yīng)的操作??梢愿鶕?jù)實(shí)際需求修改每個選項(xiàng)的處理邏輯和操作。
file=sed -n '/^\[file/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config | sed 's/[ \t]//g'
這個命令什么含義?
這個命令的含義是從指定文件中提取包含[file
開頭的行,并將其保存到變量file
中。下面是對該命令的解釋:
-
sed -n '/^\[file/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config
:這部分命令使用sed
工具從文件$CURR/../conf/extract_config
中提取特定的行。-
sed -n
:關(guān)閉默認(rèn)輸出,并使用靜默模式。 -
/^\[file/
:匹配以[file
開頭的行。 -
:a1
:定義一個標(biāo)簽a1
,用于后續(xù)跳轉(zhuǎn)。 -
n
:讀取下一行。 -
/^$/q
:如果讀取的行是空行,則退出命令執(zhí)行。 -
p
:打印滿足條件的行。 -
ba1
:跳轉(zhuǎn)到標(biāo)簽a1
,實(shí)現(xiàn)循環(huán)。
-
-
sed 's/[ \t]//g'
:這部分命令使用sed
工具刪除變量file
中的空格和制表符。-
s/[ \t]//g
:將空格和制表符替換為空字符,并應(yīng)用于整個字符串。
-
最終,通過這個命令,將文件$CURR/../conf/extract_config
中以[file
開頭的行提取出來,并存儲到變量file
中。然后對變量file
中的空格和制表符進(jìn)行刪除操作。
二、Shell腳本之shift用法
shift命令用于對參數(shù)的移動(左移),通常用于在不知道傳入?yún)?shù)個數(shù)的情況下依次遍歷每個參數(shù)然后進(jìn)行相應(yīng)處理(常見于Linux中各種程序的啟動腳本)。
示例1:
依次讀取輸入的參數(shù)并打印參數(shù)個數(shù):
-
run.sh
-
#!/bin/bash while [ $# != 0 ];do echo "第一個參數(shù)為:$1,參數(shù)個數(shù)為:$#" shift done
-
-
輸入如下命令運(yùn)行:run.sh a b c d e f
-
結(jié)果顯示如下:
-
第一個參數(shù)為:a,參數(shù)個數(shù)為:6 第一個參數(shù)為:b,參數(shù)個數(shù)為:5 第一個參數(shù)為:c,參數(shù)個數(shù)為:4 第一個參數(shù)為:d,參數(shù)個數(shù)為:3 第一個參數(shù)為:e,參數(shù)個數(shù)為:2 第一個參數(shù)為:f,參數(shù)個數(shù)為:1
-
從上可知 shift(shift 1) 命令每執(zhí)行一次,
變量的個數(shù)($#)減一(之前的$1變量被銷毀,之后的$2就變成了$1),而變量值提前一位。
同理,shift n后,前n位參數(shù)都會被銷毀,比如:
- 輸入5個參數(shù): abcd e
那么$1=a,$2=b,$3=c,$4=d,$5=e,執(zhí)行shift 3操作后,前3個參數(shù)a、b、c被銷毀,就剩下了2個參數(shù):d,e(這時d=$1,e=$2,其中d由$4—>$1,e由$5—>$2),參考示例如下:
示例2:
#!/bin/bash
echo "參數(shù)個數(shù)為:$#,其中:"
for i in $(seq 1 $#)
do
eval j=\$$i
echo "第$i個參數(shù)($"$i"):$j"
done
shift 3
echo "執(zhí)行shift 3操作后:"
echo "參數(shù)個數(shù)為:$#,其中:"
for i in $(seq 1 $#)
do
通過eval把i變量的值($i)作為變量j的名字文章來源:http://www.zghlxwxcb.cn/news/detail-525114.html
eval j=\$$i
echo "第$i個參數(shù)($"$i"):$j"
done
輸出結(jié)果為:文章來源地址http://www.zghlxwxcb.cn/news/detail-525114.html
參數(shù)個數(shù)為:5,其中:
第1個參數(shù)($1):a
第2個參數(shù)($2):b
第3個參數(shù)($3):c
第4個參數(shù)($4):d
第5個參數(shù)($5):e
執(zhí)行shift 3操作后:
參數(shù)個數(shù)為:2,其中:
第1個參數(shù)($1):d
第2個參數(shù)($2):e
三、調(diào)度作業(yè)shell腳本示例
#!/bin/bash
readonly CURR=$(readlink -m $(dirname $0))
#
path=`sed -n '/^\[path/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config | sed 's/[ \t]//g' `
file=` sed -n '/^\[file/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config | sed 's/[ \t]//g' `
date='date -d yesterday + '%Y%m%d'`
#/cib/etl_job
app_path=` sed -n '/^\[app_path/{:a1;n;/^$/q;p;ba1}' $CURR/../conf/extract_config | sed 's/[ \t]//g' `
today=`date + %Y%m%d`
mark=$1
show_usage="args: [-p, -f, -d, -h] [--path, --file, --date, --help]"
GETOPT_ARGS=`getopt -o p:f:d:h -al path:file:date:help -- "$@"`
eval set -- "$GETOPT_ARGS"
while [ -n "$1" ]
do
case "$1" in
-p|--path) test -z $2 || path=$2 shift 2;;
-f|--file) test -z $2 || path=$2 shift 2;;
-d|--date) test -z $2 || path=$2 shift 2;;
-h|--help) cat $CURR/../conf/readme1 && exit 0; shift 2;;
--) break;
*) echo $1,$2;shift 1;;
esac
done
# 日志格式
log_path="/ciblog/etl_job/$date"
flg_bak_path='/cib/etl_job/flg_bak'
flg_path='/cib/etl_job/flg'
data_path='/sftp/data'
now_date=`date -d now + "%Y%m%d%"`
> $log_path/$file"_"$date.log
echo "**********************作業(yè)1執(zhí)行日志*******************" >> $log_path/$file"_"$date.log
echo "" >>$log_path/$file"_"$date.log
echo "作業(yè)1開始執(zhí)行..." >>$log_path/$file"_"$date.log
echo "文件名稱:$file" >>$log_path/$file"_"$date.log
echo "文件日期:$date" >>$log_path/$file"_"$date.log
echo "執(zhí)行日期:$now_date" >>$log_path/$file"_"$date.log
#應(yīng)付模塊
#連接數(shù)據(jù)庫參數(shù)
#用戶名
user="cap4j"
#密碼
pass = cat $app_path/bin/passwd
function decrypt_passwd{
tmp_pass=$1
password=`echo $tmp_pass|base64 -d`
}
decrypt_passwd $pass
# ip
#host="16.7.xx.xx"
host="10.7.48.232"
#庫名
db_name="etl_job"
#sql語句:查詢當(dāng)前文件,指定日期的數(shù)據(jù)狀態(tài)
sql1="select final_status from all_table where table_name='$file' and data_time='$date'; "
# 執(zhí)行sql語句
data_status=`mysql -h "$host" -u "$user" -p "$password" -D"$db_name" -s -e "$sql1" `
#echo "data_status ==> " $data_status
#打印日志
if [ $? -eq 0 ];then
echo "文件狀態(tài)查詢成功!" >>$log_path/$file"_"$date.log
echo "文件狀態(tài)查詢成功: $data_status "
else
echo "文件狀態(tài)查詢失??!" >>$log_path/$file"_"$date.log
exit 1
fi
# 根據(jù)數(shù)據(jù)狀態(tài)執(zhí)行不同的邏輯
if [ "$data_status" -eq 1 ]
# 說明當(dāng)下日期的文件,已經(jīng)跑過了,這個是要重跑
then
#執(zhí)行重跑邏輯
echo "$file 文件 $date 號的狀態(tài)為1,執(zhí)行的是重跑任務(wù)!" >> $log_path/$file"_"$date.log
#重新復(fù)制一份flg文件
case ${mark} in
"y"){
echo "$file 特殊文件,特殊處理!"
echo "生成新的${data_path}/"$file"."$date".000000.0000.flg文件"
/bin/cp -rf ${flg_path}/"file".flg ${data_path}/$file"."$date".000000.0000.flg
};;
esac
# 刪除之前跑過的痕跡
rm -rf $path/gzip/"$file"."$date".000000.0000.data
#rm -rf $path/gzip/"$file"."$date".000000.0000.data
#rm -rf $path/gzip/"$file"."$date".000000.0000.flg
#打印日志
if [ $? -eq 0 ];then
echo "原來的過程文件刪除成功!" >> $log_path/$file"_"$date.log
else
echo "原來的過程文件刪除失?。? >> $log_path/$file"_"$date.log
exit 1
fi
# 執(zhí)行當(dāng)前作業(yè)
etl_extract(){
# "獲取字符串下標(biāo)..." >> $log_path/$file"_"$date.log
sleep 1
#echo $date
#echo $path
echo $file
bool=`ls $path | grep "$file.$date" | wc -l `
if [ $bool == 0 ];then
echo "沒有數(shù)據(jù)文件!"
exit 1
fi
# 解壓到指定路徑
gzip -cd $path/"$file"."$date".000000.0000.dat.gz > $path/gzip/"$file"."$date".000000.0000.dat
# 將解壓出來的文件進(jìn)行替換
sed -i 's/|/ /g' $path/gzip/"$file"."$date".000000.0000.dat
#打印日志
if [ $? -eq 0 ];then
echo "文件解壓成功!" >>$log_path/$file"_"$date.log
echo "文件解壓成功!"
else
echo "文件解壓失敗!" >>$log_path/$file"_"$date.log
echo "文件解壓失敗!"
exit 1
fi
# 轉(zhuǎn)碼
# iconv -f iso-8859-1 -t UTF-8 $path/../gzip/"$file"."$i".000000.0000.dat -o $path/../transcoding/"$file"."$i".000000.0000.dat
# iconv -f gb2312 -t UTF-8 $path/../gzip/"$file"."$i".000000.0000.dat -o $path/../transcoding/"$file"."$i".000000.0000.dat
# 打印日志
# esle
# echo ""$file"."$i"文件轉(zhuǎn)碼失敗!" >> $log_path/$file"_"$date.log
#exit 1
#fi
# mv $path/../transcoding/"$file"."$i".000000.0000.dat $path/../data/"$file"."$i".000000.0000.dat
# cp $path/"$file"."$i".000000.0000.flg $path/../data/"$file"."$i".000000.0000.flg
}
echo "============================執(zhí)行時間:[ `date` ]============================" >> $log_path/$file"_"$date.log
etl_extract
echo "" >> $log_path/$file"_"$date.log
echo "============================結(jié)束時間:[ `date` ]============================" >> $log_path/$file"_"$date.log
echo "" >> $log_path/$file"_"$date.log
else
# 沒有跑過,是跑批邏輯
echo "$file 文件 $date 號的狀態(tài)為0,執(zhí)行的是跑批任務(wù)!" >> $log_path/$file"_"$date.log
# 查找這個文件所有狀態(tài)為0的日期
echo "正在查找 $file 文件所有的數(shù)據(jù)狀態(tài)...." >> $log_path/$file"_"$date.log
# 從etl_job庫中查詢all_table表中該文件的數(shù)據(jù)最終狀態(tài)為零的所有日期
sql2="select data_time from all_table where table_name='$file' and final_status=0 order by data_time;"
#執(zhí)行sql語句
sql2_result=`mysql -h "$host" -u "$user" -p "$password" -D"$db_name" -s -e "$sql2" `
echo "$sql2_result" >> $log_path/$file"_"$date.log
echo "$file 文件有以上時間的數(shù)據(jù)沒有處理!" >>$log_path/$file"_"$date.log
data_file=`ls $path`
# 將能夠執(zhí)行的文件日期置空
> $app_path/date/$date/date/"$file".txt
for i in $sql2_result
do
a=0
for j in $data_file
do
if [ "$file"."$i".000000.0000.flg = "$j" ]
then
a =1
echo "$i 號的數(shù)據(jù)可以跑!" >> $log_path/$file"_"$date.log
echo "$i 號的數(shù)據(jù)可以跑!"
echo "$i" >> $app_path/date/$date/date/"$file".txt
fi
done
if [ $a -eq 0 ]
then
echo "$i 號的數(shù)據(jù)沒到!" >> $log_path/$file"_"$date.log
echo "$i 號的數(shù)據(jù)沒到!"
fi
done
# 判斷有沒有可執(zhí)行的日期
numbers =`cat $app_path/date/"$date"/date/"$file".txt | wc -l `
if [ $numbers -eq 0 ]
then
echo "沒有可以執(zhí)行的數(shù)據(jù)" >> $log_path/$file"_"$date.log
exit 1
else
date_num=`cat $app_path/date/"$date"/date/"$file".txt `
for i in $date_num
do
case ${mask} in
"y"){
echo "特殊文件,特殊處理!"
# 判斷flg文件有沒有備份過
if [ ! -f "${flg_bak_path}/${file}.${i}.000000.0000.flg" ];then
#沒有當(dāng)前flg,則將/sftp/data/"$file.$i.000000.0000.flg 移動到/cib/etl_job/flg_bak"
echo "${flg_bak_path}/${file}.${i}.000000.0000.flg 正在備份..."
mv ${data_path}/${file}.${i}.000000.0000.flg ${flg_bak_path}
if [ $? -eq 0 ];then
echo "${file}.${date}.000000.0000.flg 文件備份成功!"
else
echo "${file}.${date}.000000.0000.flg 文件備份失??!"
exit 1
fi
else
echo "${flg_bak_path}/${file}.${i}.000000.0000.flg存在,不需要備份!"
fi
# 復(fù)制新的flg文件
echo "生成新的"$file"."$i".000000.0000.flg文件!"
/bin/cp -rf ${flg_path}/"file".flg ${data_path}/$file"."$i".000000.0000.flg
};;
esca
# 刪除之前跑過的痕跡
rm -rf $path/gzip/"$file"."$i".000000.0000.data
#
if [ $? -eq 0 ];then
echo "初始化成功!" >> $log_path/$file"_"$date.log
else
echo "初始化失??!" >> $log_path/$file"_"$date.log
exit 1
fi
etl_extract(){
bool=` ls $path | grep "$file.$i" | grep wc -l `
if [ $bool == 0 ];then
echo "沒有數(shù)據(jù)文件!"
exit 1
fi
# 解壓到指定路徑
gzip -cd $path/"$file"."$i".000000.0000.dat.gz > $path/gzip/"$file"."$i".000000.0000.dat
# 將解壓出來的文件進(jìn)行替換
sed -i 's/|/ /g' $path/gzip/"$file"."$i".000000.0000.dat
# 打印日志
if [ $? -eq 0 ];then
echo ""$file"."$i"文件解壓成功!" >> $log_path/$file"_"$date.log
else
echo ""$file"."$i"文件解壓失??!" >> $log_path/$file"_"$date.log
exit 1
fi
#轉(zhuǎn)碼
# iconv -f iso-8859-1 -t UTF-8 $path/../gzip/"$file"."$i".000000.0000.dat -o $path/../transcoding/"$file"."$i".000000.0000.dat
# iconv -f gb2312 -t UTF-8 $path/../gzip/"$file"."$i".000000.0000.dat -o $path/../transcoding/"$file"."$i".000000.0000.dat
# 打印日志
# esle
# echo ""$file"."$i"文件轉(zhuǎn)碼失敗!" >> $log_path/$file"_"$date.log
#exit 1
#fi
# mv $path/../transcoding/"$file"."$i".000000.0000.dat $path/../data/"$file"."$i".000000.0000.dat
# cp $path/"$file"."$i".000000.0000.flg $path/../data/"$file"."$i".000000.0000.flg
}
echo "============================執(zhí)行時間:[ `date` ]============================" >> $log_path/$file"_"$date.log
etl_extract
echo "" >> $log_path/$file"_"$date.log
echo "============================結(jié)束時間:[ `date` ]============================" >> $log_path/$file"_"$date.log
echo "" >> $log_path/$file"_"$date.log
done
fi
fi
到了這里,關(guān)于Shell腳本參數(shù)獲取的兩種方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!