我总是每天使用参数开发我的shell脚本,甚至在开发一些自动化脚本时。但是,最近我尝试了一种不同的方法,将环境变量导出到我的脚本中。
#!/bin/bash
: ${USER?"Requires USER"}
: ${FIRST_NAME?"Requires FIRST_NAME"}
: ${LAST_NAME?"Requires LAST_NAME"}
: ${EMAIL?"Requires EMAIL"}
set -x
setup_git_account(){
su - "${USER}" -c "git config --global user.name '${FIRST_NAME} ${LAST_NAME}'"
su - "${USER}" -c "git config --global user.email '${EMAIL}'"
}
setup_git_account
这确保了更小的代码,在初始化所有必需变量时可以轻松检查,并且一旦在外部声明所有变量,就可以更好地理解脚本正在做什么。
export USER='john' && export FIRST_NAME='John' && export LAST_NAME='Doe' && export EMAIL='john.doe@email.com' && setup_git_account.sh
如果使用接收参数实现,可以用这样表示:
setup_git_account.sh --user 'john' --firstname 'John' --lastname 'Doe' --email 'john.doe@email.com'
但是,最后一个,需要更多行代码来实现getopts
切换案例,检查传递的参数值等。
无论如何,我知道我们已经习惯了第二种方法,但我认为第一种方法也有几个好处。如果所提出的方法之间存在任何不利之处,我想向您倾听更多信息。我应该使用哪一个?
谢谢!
答案 0 :(得分:2)
有点偏离主题, static char TOUCH_DEVICE[256] = "/dev/uinput";
struct uinput_user_dev touch_uidev;
struct input_event moveev[2];
struct input_event touchev;
static int touchfd = -1;
// Opening device
if((touchfd = open(TOUCH_DEVICE, O_WRONLY | O_NONBLOCK)) == -1)
{
printf("cannot open touch device %s\n", TOUCH_DEVICE);
exit(EXIT_FAILURE);
}
printf("Registering event types...\n");
if(ioctl(touchfd, UI_SET_EVBIT, EV_SYN) < 0)
die("error: ioctl");
if(ioctl(touchfd, UI_SET_EVBIT, EV_ABS) < 0)
die("error: ioctl");
if(ioctl(touchfd, UI_SET_ABSBIT, ABS_X) < 0)
die("error: ioctl");
if(ioctl(touchfd, UI_SET_ABSBIT, ABS_Y) < 0)
die("error: ioctl");
memset(&touch_uidev, 0, sizeof(touch_uidev));
snprintf(touch_uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-mouse");
touch_uidev.id.bustype = BUS_USB;
touch_uidev.id.vendor = 0x1;
touch_uidev.id.product = 0x1;
touch_uidev.id.version = 1;
touch_uidev.absmin[ABS_X] = 0;
touch_uidev.absmax[ABS_X] = 640;
touch_uidev.absmin[ABS_Y] = 0;
touch_uidev.absmax[ABS_Y] = 480;
if(write(touchfd, &touch_uidev, sizeof(touch_uidev)) < 0)
die("error: write");
if(ioctl(touchfd, UI_DEV_CREATE) < 0)
die("error: ioctl");
printf("Mouse fd opened successfully.\n");
//Injecting events
memset(moveev, 0, sizeof(moveev));
moveev[0].type = EV_ABS;
moveev[0].code = ABS_X;
moveev[0].value = x;
moveev[1].type = EV_ABS;
moveev[1].code = ABS_Y;
moveev[1].value = y;
if(write(touchfd, moveev, sizeof(moveev)) < 0)
die("error: write");
memset(&touchev, 0, sizeof(touchev));
touchev.type = EV_SYN;
touchev.code = 0;
touchev.value = 0;
if(write(touchfd, &touchev, sizeof(touchev)) < 0)
die("error: write");
的环境变量的调用语法可以更短,不需要bash
:
export
答案 1 :(得分:1)
您的所有值都不是可选的;我只想使用位置参数。
: ${1?"Requires USER"}
: ${2?"Requires FIRST_NAME"}
: ${3?"Requires LAST_NAME"}
: ${4?"Requires EMAIL"}
sudo -u "$1" git config --global user.name "$2 $3" user.email "$4"
为用户提供以任意顺序指定值的方式只是一种不必要的复杂化。
您只需使用
调用脚本即可setup_git_account.sh 'john' 'John' 'Doe' 'john.doe@email.com'
重新考虑名字和姓氏是否需要单独的参数。无论如何,它们被脚本组合成git config
的单个参数;只需将名称作为单个参数。
setup_git_account.sh 'john' 'John Doe' 'john.doe@email.com'
(根据需要对脚本进行适当的更改)。
答案 2 :(得分:0)
我从不使用你的方法。我认为使用参数没有任何缺点。这是使用参数的常用方法,如果您使用的是longopts,则可以进行自我描述。 在我看来,如果您需要不同脚本中的数据,env vars是一种解决方案。
在您不允许更改环境的系统上运行此类脚本时可能会遇到问题。
答案 3 :(得分:0)
我使用guide对您的变量进行了参数化,我后来写了一段时间,甚至添加了--help
。
此解决方案接受环境变量和选项(将胜过变量):
while getopts e:f:hl:u:-: arg; do
case "$arg" in
e ) EMAIL="$OPTARG" ;;
f ) FIRST_NAME="$OPTARG" ;;
h ) do_help ;;
l ) LAST_NAME="$OPTARG" ;;
u ) USER_NAME="$OPTARG" ;;
- ) LONG_OPTARG="${OPTARG#*=}"
case $OPTARG in
email=?* ) EMAIL="$LONG_OPTARG" ;;
first*=?* ) FIRST_NAME="$LONG_OPTARG" ;;
help* ) do_help ;;
last*=?* ) LAST_NAME="$LONG_OPTARG" ;;
user=?* ) USER_NAME="$LONG_OPTARG" ;;
* ) echo "Illegal option/missing argument: --$OPTARG" >&2; exit 2 ;;
esac ;;
* ) exit 2 ;; # error messages for short options already given by getopts
esac
done
shift $((OPTIND-1))
HELP=" - see ${0##*/} --help"
: ${USER_NAME?"Requires USER_NAME$HELP"}
: ${FIRST_NAME?"Requires FIRST_NAME$HELP"}
: ${LAST_NAME?"Requires LAST_NAME$HELP"}
: ${EMAIL?"Requires EMAIL$HELP"}
su - "$USER_NAME" -c "git config --global user.name '$FIRST_NAME $LAST_NAME'"
su - "$USER_NAME" -c "git config --global user.email '$EMAIL'"
请注意,我将$USER
更改为$USER_NAME
以避免与您的本地环境发生冲突($USER
您的用户名在本地Linux系统上!)< / p>
您还可以从系统中提取用户的全名:
FULL_NAME="$(getent passwd |awk -v u="$USER_NAME" -F: '$1 == u { print $5 }')"
(我认为没有理由将FIRST_NAME和LAST_NAME分开;你对Jean Claude Van Damme做了什么?他们只是一起使用。另请注意,并非所有用户都会在passwd文件中使用全名。)
这使用do_help
来显示--help
输出。这是一个如何看的例子(我把它放在脚本的顶部,所以有人只是阅读它可以得到概要;它不在上面的代码块中,因为我想阻止该块获得滚动条):
do_help() { cat <</help
Usage: ${0##*/} [OPTIONS]
-u USER_NAME, --user=USER_NAME
-f FIRST_NAME, --firstname=FIRST_NAME
-l LAST_NAME, --lastname=LAST_NAME
-e EMAIL, --email=EMAIL
Each option may also be passed through the environment as e.g. $EMAIL
Code taken from https://stackoverflow.com/a/41515444/519360
/help
}