sudo,坏替换,间接参数扩展

时间:2016-09-13 21:15:39

标签: shell unix

这是一个尝试做“ifndef' (ifndef.sh):

if

当我尝试在另一个文件(#!/bin/bash ################# __ifndef__ ################# MAIN_SCRIPT=$(cd "$(dirname "$0")" && pwd -P)"/$(basename $0)" script_path=$(echo $MAIN_SCRIPT | sed -e "s@/@_@g" -e "s@\.@_@g" -e "s@-@_@") define_var="ALREADY_SOURCED_$script_path" echo "Main_script: $MAIN_SCRIPT" echo "script_path: $script_path" echo "define_var: $define_var" echo "??: ${!define_var}" [[ ! -z ${!define_var} ]] && return export ALREADY_SOURCED_$script_path="defined" ################# __ifndef__ ################# )中执行此代码时:

main.sh

使用sudo,我总是会收到此错误:

. ./ifndef.sh

echo "TEST !"

我用来启动脚本的命令是:./main.sh: 10: ./ifndef.sh: Bad substitution

我不知道为什么./main.sh有问题。

3 个答案:

答案 0 :(得分:2)

您无法使用sh运行bash脚本 - 它只能与bash一起运行。特别是,您在这里使用了几个功能(包括间接扩展la ${!foo}和扩展测试运算符[[ ]]),这些功能不属于POSIX sh标准,因此无法保证在使用sh运行时可用。

而不是运行sh yourscript,而是运行bash yourscript或仅./yourscript(已授予shebang设置并执行权限);而不是使用#!/bin/sh启动它,而是使用#!/bin/bash启动它。如果这是来源,请确保您从中获取的脚本本身是以bash开头的。

另一件事是你的转义不够完整,以确保你的$script_path确实是一个有效的shell变量名。只需切换到使用关联数组,而不是试图解决这个问题 - 键可以包含除NUL之外的任何字符,无论如何在UNIX路径中无效:

#!/usr/bin/env bash
# uses the first bash interpreter on the PATH, so on MacOS X, can use MacPorts bash
# if sourcing this, be sure to do the same in the script you're sourcing it from.

### start version check
[ -n "$BASH_VERSION" ] || {
  echo "Current shell is not bash; must use bash 4.0 or later" >&2
  return 1 || exit 1
}
[[ $BASH_VERSION =~ ^([4-9][.]|[0-9][0-9]+) ]] || {
  echo "Bash version 4 or newer is required (using $BASH_VERSION)" >&2
  return 1 || exit 1
}
### end version check

### start redefinition check
declare -A already_sourced
[[ ${already_sourced[$BASH_SOURCE]} ]] && return
already_sourced[$BASH_SOURCE]=1
### end redefinition check

上述内容需要Bash 4.x,它不随MacOS一起提供,但可通过MacPorts获得。

答案 1 :(得分:1)

使用BASH,您可以跳过所有sed执行BASH本身的所有替换:

#!/bin/bash

################# __ifndef__ #################
MAIN_SCRIPT=$(cd "$(dirname "$0")" && pwd -P)"/$(basename $0)"
script_path="${MAIN_SCRIPT//[\/.-]/_}"
echo "Main_script: $MAIN_SCRIPT"
echo "script_path: $script_path"
define_var="ALREADY_SOURCED_$script_path"
echo "define_var: $define_var"
echo "??: ${!define_var}"
[[ ! -z ${!define_var} ]] && return
declare -x $define_var="defined"
echo "##: ${!define_var}"
################# __ifndef__ #################

答案 2 :(得分:0)

我的坏!

我只需添加'#!/ bin / bash'在内部脚本(main.sh here)