eval不在shellscript中工作

时间:2016-03-31 11:28:39

标签: shell

我试图使用apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.astro.famouspandit" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" multiDexEnabled true } dexOptions { javaMaxHeapSize "4g" preDexLibraries = false } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.1' compile 'com.android.support:design:23.2.1' compile 'com.android.support:cardview-v7:23.2.1' compile 'com.android.support:recyclerview-v7:23.2.1' compile 'com.github.medyo:fancybuttons:1.5@aar' compile 'com.google.android.gms:play-services:8.4.0' compile 'com.astuetz:pagerslidingtabstrip:1.0.1' compile 'com.github.chenupt.android:springindicator:1.0.2@aar' compile 'com.android.support:support-v4:23.2.1' compile 'com.github.lzyzsd:circleprogress:1.1.0@aar' compile 'com.squareup.okhttp:okhttp:2.4.0' compile files('libs/aws-android-sdk-apigateway-core-2.2.7.jar') 在运行时通过名称选择变量的值,但是如果eval(连字符)在名称中,我就不会得到它的值。

-

RESULT

ENV=dev
REGION=us-east-1

DBUSERNAME=DB_USER_${ENV}_$REGION
DBPASSWORD=DB_PASS_${ENV}_$REGION

eval "USERNAME=\${${DBUSERNAME}}"
eval "PASSWORD=\${${DBPASSWORD}}"

echo USERNAME=$USERNAME
echo PASSWORD=$PASSWORD

预期结果

echo USERNAME=east-1
echo PASSWORD=east-1

如果名称中没有连字符,则工作正常。

3 个答案:

答案 0 :(得分:4)

研究

我们可以通过在-x选项中运行此命令来查看正在发生的事情,以跟踪​​执行情况:

$ sh -x ./36332134.sh 
+ ENV=dev
+ REGION=us-east-1
+ DBUSERNAME=DB_USER_dev_us-east-1
+ DBPASSWORD=DB_PASS_dev_us-east-1
+ eval USERNAME=${DB_USER_dev_us-east-1}
+ USERNAME=east-1
+ eval PASSWORD=${DB_PASS_dev_us-east-1}
+ PASSWORD=east-1
+ echo USERNAME=east-1
USERNAME=east-1
+ echo PASSWORD=east-1
PASSWORD=east-1

请注意,eval USERNAME=${DB_USER_dev_us-east-1}为我们提供了USERNAME=east-1。这个参数的扩展有效,如Bash手册中所述:

  

当不使用下面记录的表单(例如:-)执行子字符串扩展时,bash测试未设置的参数   或者为null。省略冒号只会导致参数测试   这是未设置的。

     

<强> ${parameter:-word}
  使用默认值。如果parameter未设置或为null,则word的扩展将被替换。否则,parameter的值   被替代。

由于$DB_USER_dev_us未设置,因此${DB_USER_dev_us-east-1}的扩展为east-1

变通方法

Shell在变量名称(包括环境变量)中不允许-。我猜DB_USER_dev_us-east-1是由一些非shell程序设置的?在这种情况下,我认为你需要一个类似的非shell程序来检索它。我测试引用了-,但无济于事。

如果可以使用Bash作为shell,则可能需要使用关联数组而不是组成变量名。

如果您能够更改环境变量,可以考虑将-更改为(比方说)_,然后使用(Bash)${REGION//-/_}或(否则){{1转换名称:

tr

答案 1 :(得分:1)

您正在评估/扩展一些次数。

Toby的回答是完全正确的(并且显示了针对此类问题的正确调试技术)但问题的解决方案是解开一个级别的扩展。

你写了

eval "USERNAME=\${${DBUSERNAME}}"

成为

eval "USERNAME=\${DB_USER_dev_us-east-1}"

然后以eval作为

运行
USERNAME=${DB_USER_dev_us-east-1}

成为

USERNAME=east-1

但是你想在第一次扩张后停止。那是

eval "USERNAME=\${DB_USER_dev_us-east-1}"

已经完成了您想要的扩展并获得了所需的结果。所以你不想要\${...}位或eval。刚

USERNAME=DB_USER_dev_us-east-1

你从

获得
USERNAME=${DBUSERNAME}

除非我遗漏了某些内容,否则你的例子不准确。

答案 2 :(得分:0)

正如他们已经解释了问题,这是你可以做的事情

$> more a.sh
ENV=dev
REGION=us-east-1

DBUSERNAME=DB_USER_${ENV}_$REGION
DBPASSWORD=DB_PASS_${ENV}_$REGION

eval "USERNAME=${DBUSERNAME}"
eval "PASSWORD=${DBPASSWORD}"

echo USERNAME=$USERNAME
echo PASSWORD=$PASSWORD

结果

$> ./a.sh
USERNAME=DB_USER_dev_us-east-1
PASSWORD=DB_PASS_dev_us-east-1