Shell脚本参数获取的两种方式 您所在的位置:网站首页 shell第一个参数 Shell脚本参数获取的两种方式

Shell脚本参数获取的两种方式

2024-07-15 12:25| 来源: 网络整理| 查看: 265

一、Shell 参数获取的两种方式 方式一固定顺序传参 示例

新建一个test.sh文件

#!/bin/bash echo "shell 名称 = $0" echo "参数1 = $1" echo "参数2 = $2" echo "参数3 = $3" echo "参数4 = $4" echo "参数5 = $5"

执行脚本 : sh test.sh 5 6 3 6 2

输出的结果:

shell 名称 = test.sh 参数1 = 5 参数2 = 6 参数3 = 3 参数4 = 6 参数5 = 2

使用该方式有两点需要注意的地方:“$0” 表示的是脚本名称本身

优点 : 获取参数方便、简洁缺点 :必须按照指定的顺序输入参数,中间不能漏参数。否则参数将会产生错乱。 方式二 使用 getopts 方式获取 如果需要实现类似 job_3.sh -f -d 指定参数值的方式,则推荐使用此种方式。 使用该方式需要使用到Shell内置的函数"getopts"。 在使用之前你需要知道一下几个内置参数的意义: 1.optstring option :字符串,当中为参数选项,会逐个匹配。 2.varname :每次匹配成功的选项 3.arg :参数值 4.$OPTIND :option index,会逐个递增,初始值为1 5.$OPTARG :option argument,不同情况下会有不同的值

该函数的具体使用方式 : getopts [option[:]] VARIABLE 参数说明:

[option[:]] 表示参数,以"?️b:c:"的方式设置 #####注意细节: 以":"开头时:getopts不会提示错误信息,会区分invalid option错误和miss option argument,两种错误的值不一样。invalid option错误时,VARIABLE会被设为*?。为出问题的option。miss option argument时,VARIABLE会被设为*。$OPTARG为出问题的option。不以":"开头时:getopts会提示错误信息。会根据invalid option错误和miss option argument。提示两种不同的错误。VARIABLE都会被设为?。$OPTARG都为空。如果option后面跟了":"表示该option可以接收参数,参数(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 "未知参数$opt" echo "参数值$OPTARG" ;; ?) echo "未知参数$opt" echo "参数值$OPTARG" ;; esac done

执行:sh getopt.sh -a 12 -p 32 -s string -n 你好 -r 世界

输出:

12 32 string 你好 install.sh: 非法选项 -- r 未知参数? 参数值 可选参数示例 脚本可以传1到多个参数该如何处理?如下面例子: #!/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解析命令行参数的示例。

代码解释如下:

GETOPT_ARGS=$(getopt -o p:f:d:h -al path:file:date:help -- "$@")

使用getopt命令解析命令行参数,并将结果保存到GETOPT_ARGS变量中。-o后面跟短选项,例如p:f:d:h表示短选项为-p、-f、-d和-h。-l后面跟长选项,例如path:file:date:help表示长选项为--path、--file、--date和--help。--表示选项结束,之后的参数将被视为位置参数。"$@"表示将脚本接收到的所有参数传递给getopt命令。

eval set -- "$GETOPT_ARGS"

将GETOPT_ARGS的值设置为新的参数列表,相当于重置了脚本中的位置参数。这样,后续的$1、$2等就可以用于处理解析后的命令行参数。

while [ -n "$1" ]

这是一个循环语句,用于逐个处理命令行参数,直到所有参数都被处理完毕。

case "$1" in ... esac

这是一个条件判断语句,根据当前参数的值执行相应的操作。

-p | --path) test -z $2 || path=$2; shift 2;;

当参数是-p或--path时,将下一个参数(即$2)赋值给path变量,并通过shift 2将已处理的两个位置参数移除。

-f | --file) test -z $2 || file=$2; shift 2;;

当参数是-f或--file时,将下一个参数(即$2)赋值给file变量,并通过shift 2将已处理的两个位置参数移除。

-d | --date) test -z $2 || date=$2; shift 2;;

当参数是-d或--date时,将下一个参数(即$2)赋值给date变量,并通过shift 2将已处理的两个位置参数移除。

-h | --help) cat $CURR/../conf/readme1 && exit 0; shift 2;;

当参数是-h或--help时,打印readme1文件的内容并退出脚本。

--) break;;

当遇到--标记时,停止循环。

*) echo $1 , $2; shift 1;;

对于其他未匹配的参数,打印参数的值,并通过shift 1将已处理的一个位置参数移除。

通过以上步骤,脚本会逐个处理命令行参数,并根据参数的类型进行相应的操作。可以根据实际需求修改每个选项的处理逻辑和操作。

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:关闭默认输出,并使用静默模式。/^\[file/:匹配以[file开头的行。:a1:定义一个标签a1,用于后续跳转。n:读取下一行。/^$/q:如果读取的行是空行,则退出命令执行。p:打印满足条件的行。ba1:跳转到标签a1,实现循环。

sed 's/[ \t]//g':这部分命令使用sed工具删除变量file中的空格和制表符。

s/[ \t]//g:将空格和制表符替换为空字符,并应用于整个字符串。

最终,通过这个命令,将文件$CURR/../conf/extract_config中以[file开头的行提取出来,并存储到变量file中。然后对变量file中的空格和制表符进行删除操作。

二、Shell脚本之shift用法

shift命令用于对参数的移动(左移),通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理(常见于Linux中各种程序的启动脚本)。

示例1:

依次读取输入的参数并打印参数个数:

run.sh

#!/bin/bash while [ $# != 0 ];do echo "第一个参数为:$1,参数个数为:$#" shift done

输入如下命令运行:run.sh a b c d e f

结果显示如下:

第一个参数为:a,参数个数为:6 第一个参数为:b,参数个数为:5 第一个参数为:c,参数个数为:4 第一个参数为:d,参数个数为:3 第一个参数为:e,参数个数为:2 第一个参数为:f,参数个数为:1

从上可知 shift(shift 1) 命令每执行一次,变量的个数($#)减一(之前的$1变量被销毁,之后的$2就变成了$1),而变量值提前一位。

同理,shift n后,前n位参数都会被销毁,比如:

输入5个参数: abcd e

那么$1=a,$2=b,$3=c,$4=d,$5=e,执行shift 3操作后,前3个参数a、b、c被销毁,就剩下了2个参数:d,e(这时d=$1,e=$2,其中d由$4—>$1,e由$5—>$2),参考示例如下:

示例2: #!/bin/bash echo "参数个数为:$#,其中:" for i in $(seq 1 $#) do eval j=\$$i echo "第$i个参数($"$i"):$j" done shift 3 echo "执行shift 3操作后:" echo "参数个数为:$#,其中:" for i in $(seq 1 $#) do

通过eval把i变量的值($i)作为变量j的名字

eval j=\$$i echo "第$i个参数($"$i"):$j" done

输出结果为:

参数个数为:5,其中: 第1个参数($1):a 第2个参数($2):b 第3个参数($3):c 第4个参数($4):d 第5个参数($5):e 执行shift 3操作后: 参数个数为:2,其中: 第1个参数($1):d 第2个参数($2):e 三、调度作业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 "**********************作业1执行日志*******************" >> $log_path/$file"_"$date.log echo "" >>$log_path/$file"_"$date.log echo "作业1开始执行..." >>$log_path/$file"_"$date.log echo "文件名称:$file" >>$log_path/$file"_"$date.log echo "文件日期:$date" >>$log_path/$file"_"$date.log echo "执行日期:$now_date" >>$log_path/$file"_"$date.log #应付模块 #连接数据库参数 #用户名 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语句:查询当前文件,指定日期的数据状态 sql1="select final_status from all_table where table_name='$file' and data_time='$date'; " # 执行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 "文件状态查询成功!" >>$log_path/$file"_"$date.log echo "文件状态查询成功: $data_status " else echo "文件状态查询失败!" >>$log_path/$file"_"$date.log exit 1 fi # 根据数据状态执行不同的逻辑 if [ "$data_status" -eq 1 ] # 说明当下日期的文件,已经跑过了,这个是要重跑 then #执行重跑逻辑 echo "$file 文件 $date 号的状态为1,执行的是重跑任务!" >> $log_path/$file"_"$date.log #重新复制一份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 # 执行当前作业 etl_extract(){ # "获取字符串下标..." >> $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 "没有数据文件!" exit 1 fi # 解压到指定路径 gzip -cd $path/"$file"."$date".000000.0000.dat.gz > $path/gzip/"$file"."$date".000000.0000.dat # 将解压出来的文件进行替换 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 # 转码 # 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"文件转码失败!" >> $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 "============================执行时间:[ `date` ]============================" >> $log_path/$file"_"$date.log etl_extract echo "" >> $log_path/$file"_"$date.log echo "============================结束时间:[ `date` ]============================" >> $log_path/$file"_"$date.log echo "" >> $log_path/$file"_"$date.log else # 没有跑过,是跑批逻辑 echo "$file 文件 $date 号的状态为0,执行的是跑批任务!" >> $log_path/$file"_"$date.log # 查找这个文件所有状态为0的日期 echo "正在查找 $file 文件所有的数据状态...." >> $log_path/$file"_"$date.log # 从etl_job库中查询all_table表中该文件的数据最终状态为零的所有日期 sql2="select data_time from all_table where table_name='$file' and final_status=0 order by data_time;" #执行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 文件有以上时间的数据没有处理!" >>$log_path/$file"_"$date.log data_file=`ls $path` # 将能够执行的文件日期置空 > $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 号的数据可以跑!" >> $log_path/$file"_"$date.log echo "$i 号的数据可以跑!" echo "$i" >> $app_path/date/$date/date/"$file".txt fi done if [ $a -eq 0 ] then echo "$i 号的数据没到!" >> $log_path/$file"_"$date.log echo "$i 号的数据没到!" fi done # 判断有没有可执行的日期 numbers =`cat $app_path/date/"$date"/date/"$file".txt | wc -l ` if [ $numbers -eq 0 ] then echo "没有可以执行的数据" >> $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 #没有当前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 # 复制新的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 "没有数据文件!" exit 1 fi # 解压到指定路径 gzip -cd $path/"$file"."$i".000000.0000.dat.gz > $path/gzip/"$file"."$i".000000.0000.dat # 将解压出来的文件进行替换 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 #转码 # 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"文件转码失败!" >> $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 "============================执行时间:[ `date` ]============================" >> $log_path/$file"_"$date.log etl_extract echo "" >> $log_path/$file"_"$date.log echo "============================结束时间:[ `date` ]============================" >> $log_path/$file"_"$date.log echo "" >> $log_path/$file"_"$date.log done fi fi


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有