如何让Shell中从文件读取的嵌套变量被正确展开替换
如何让Shell中从文件读取的嵌套变量被正确展开替换
我懂你遇到的问题了——从配置文件里抠出来的字符串里带着$ID,但Shell就是不肯把它换成实际的Some_ID,直接原封不动输出了$ID本身对吧?这是因为从文件读取或者通过命令替换得到的字符串,Shell默认不会二次解析里面的变量引用,得咱们手动触发这个展开操作才行。下面给你几个实用的解决办法,你可以根据自己的场景选:
方法1:用eval命令强制解析变量
eval的作用就是把字符串重新交给Shell解析一遍,这样里面的变量引用就会被展开。不过要提醒你:如果你的配置文件内容是不可信的(比如可能被恶意修改),eval有安全风险,因为它会执行字符串里的任意Shell命令。
修改后的代码示例:
ID="Some_ID" CONFIG_FILE="/etc/config.file" VAR3=$(grep -i "^shell=" "$CONFIG_FILE") # 用$()代替反引号,可读性更好 VAR3=${VAR3#*"-t"} VAR3=$(echo "$VAR3" | cut -d ' ' -f 1) # 新增这一行,让eval重新解析字符串,展开$ID VAR3=$(eval echo "$VAR3") echo "$VAR3" echo "$ID"
这样运行后,VAR3就会输出path/to/some/data/Some_ID/state了。
方法2:用envsubst安全替换环境变量
envsubst是专门用来替换字符串中的环境变量的工具,它只会替换变量,不会执行命令,比eval安全很多。使用前需要把ID导出为环境变量,这样envsubst才能识别它。
代码示例:
ID="Some_ID" export ID # 导出为环境变量 CONFIG_FILE="/etc/config.file" VAR3=$(grep -i "^shell=" "$CONFIG_FILE") VAR3=${VAR3#*"-t"} VAR3=$(echo "$VAR3" | cut -d ' ' -f 1) # 只替换$ID变量,避免误替换其他$开头的内容 VAR3=$(echo "$VAR3" | envsubst '$ID') echo "$VAR3"
如果你的字符串里有多个需要替换的变量,可以把它们都列在envsubst后面,比如envsubst '$ID $OTHER_VAR',这样只会替换指定的变量,更稳妥。
方法3:用Shell参数展开手动替换
如果你的场景里只需要替换$ID这一个固定变量,直接用Shell的参数展开做字符串替换最安全,也不需要额外工具。
代码示例:
ID="Some_ID" CONFIG_FILE="/etc/config.file" VAR3=$(grep -i "^shell=" "$CONFIG_FILE") VAR3=${VAR3#*"-t"} VAR3=$(echo "$VAR3" | cut -d ' ' -f 1) # 把字符串里的字面量$ID替换为实际的ID变量值,\$是转义$避免被Shell解析 VAR3=${VAR3//\$ID/$ID} echo "$VAR3"
这里的${VAR3//\$ID/$ID}表示在VAR3中,把所有出现的$ID(字面量)替换成$ID变量的实际值。
备注:内容来源于stack exchange,提问作者Krzysiek
相关产品推荐
相关产品推荐

