这个命令有什么问题吗?似乎存在语法错误,但我不知道在哪里:
sh -c 'mongodump --host mongo_db --gzip --db db $$(if [ $TYPE = "hour" ]; then echo "--archive=/backup/hour/$$(date +"%H").gz"; elif [ $TYPE = "day" ]; then echo --archive=/backup/day/$$(date +"%d").gz; fi)'
我需要根据 TYPE 变量设置存档名称。
- 如果类型是“小时”,输出应该是例如
/backup/hour/10.gz
- 如果类型是“day”,输出应该是例如
/backup/day/1.gz
- 如果类型是“月”,输出应该是例如
/backup/2017-09.gz
答案1
sh -c 'echo mongodump --host mongo_db --gzip --db db --archive="$(
case "$1" in
hour) f="%H";;
day) f="%d";;
month) f="%Y-%m";;
*) f="unknown"; set -- "";;
esac
date "+/backup/$1/$f.gz"
)"' x "$TYPE"
- 干燥
case
比 long 更具可读性if/elif/elif...
- 这
x "$TYPE"
是一种将“外部”变量传递到 sh 主体中而无需玩引用游戏的方法。 sh 主体中的“x”变为 $0,$TYPE 变为 $1。 - 内部允许换行
$(...)
- 您可以在格式字符串
%
中放置非指令date
。
答案2
您有未加引号的变量 ( $TIME
) 和语法错误 ( $$(...)
)。此外,如果TYPE
是 shell 变量(而不是环境变量),则其值在单引号脚本中根本不可见sh -c
。
该声明应该类似于
sh -c "mongodump --host mongo_db --gzip --db db \"$(if [ \"$TYPE\" = \"hour\" ]; then echo \"--archive=/backup/hour/$(date +%H).gz\"; elif [ \"$TYPE\" = \"day\" ]; then echo --archive=/backup/day/$(date +%d).gz; fi)\""
(或者其他的东西...)
正确引用是有问题的,因为您希望 shell$TYPE
在最里面的子 shell 中展开,并且仍然用双引号引起来。
如果你不需要sh -c
(我可以看到没有什么需要它),它会变得更容易一些:
mongodump --host mongo_db --gzip --db db "$(if [ "$TYPE" = "hour" ]; then echo "--archive=/backup/hour/$(date +%H).gz"; elif [ "$TYPE" = "day" ]; then echo "--archive=/backup/day/$(date +%d).gz"; fi)"
但是,由于这会给出一个空的命令替换 if $TYPE
is isn't day
Nor hour
,所以我建议您这样做:
case "$TYPE" in
hour) archive="/backup/hour/$(date +%H).gz" ;;
day) archive="/backup/day/$(date +%d).gz" ;;
*)
printf 'Error: Unknown TYPE "%s"\n' "$TYPE" >&2
exit 1 ;;
esac
sh -c "mongodump --host mongo_db --gzip --db db --archive=$archive"
# or just
mongodump --host mongo_db --gzip --db db --archive="$archive"
这使得它更容易阅读、理解和维护。
答案3
如果TYPE
未设置、为空或完全由空格组成,则您的语句归结为if [ = "hour" ]
语法错误。
由于您使用的是sh
,因此常见的解决方法是使用前缀:if [ "x$TYPE" = "xhour" ]
您不能简单地使用弱引号,因为 a""
也会解析为if [ = "hour" ]
;至少与sh
. bash
当使用更强大的双括号语法(例如if [[ "$TYPE" = "hour" ]]
)时,将做正确的事情,而无需求助于前缀或后缀。