【问题标题】:sed | replace value with environment variable containing double quotessed |用包含双引号的环境变量替换值
【发布时间】:2021-01-21 07:41:42
【问题描述】:

我的环境变量包含如下双引号:

$echo $CONNECT_SASL_JAAS_CONFIG
org.apache.kafka.common.security.plain.PlainLoginModule required username="USER" password="XXXX/YYY";

“导出”命令的输出:

declare -x CONNECT_SASL_JAAS_CONFIG="org.apache.kafka.common.security.plain.PlainLoginModule required username=\"USER\" password=\"XXXX/YYY\";

我的模板文件内容如下(props.txt):

sasl.jaas.config = JAAS_CONF

我尝试使用以下命令将 JAAS_CONF 替换为 env 变量:

 sed  -e  "s/JAAS_CONF/$CONNECT_SASL_JAAS_CONFIG/g;" props.txt

这会产生以下错误:

/tmp# sed -e "s/JAAS_CONF/$CONNECT_CONSUMER_SASL_JAAS_CONFIG/g;" props.txt sed: -e expression #1, char 168: `s' 的未知选项

关于如何解决这个问题的任何提示?

更新:

注意

  • “密码”包含“/”字符
  • CONNECT_CONSUMER_SASL_JAAS_CONFIG 末尾有一个换行符
  • 我需要再次逃脱双打。

所以最后我的解决方案是:

  export TMP_JAAS=${SASL_JAAS_CONFIG//$'\"'/'\\"'}
  export PARSED_JAAS=${TMP_JAAS//$'\n'/\ }
  sed  -e  "s|JAAS_CONF|${PARSED_JAAS//$'\n'/\ }|g" file.cong > /tmp/app.conf

【问题讨论】:

    标签: linux bash shell sed


    【解决方案1】:

    使用envsubst:

    假设您有一个字符串STRING,您想用变量VARIABLE_STRING 替换它。那么我会建议以下方法:

    1. 用正确的 shell 变量名替换所有感兴趣的变量(包括 $
    2. export所有感兴趣的变量
    3. 使用envsubst 执行替换

    这是一个例子:

    $ export VARIABLE_STRING='foo "bar" qux'
    $ echo "This is the string 'STRING'" | sed 's/\bSTRING\b/$VARIABLE_STRING/g' | envsubst '$VARIABLE_STRING'
    This is the string 'foo "bar" qux'
    

    您可以根据自己的喜好进行调整。请阅读[U&L] Replacing only specific variables with envsubst 了解更多信息。

    使用 GNU awk:

    如果你不能使用envsubst,你可以在awk中写一些东西。 GNU awk 可以使用ENVIRON 数组访问环境,该数组是从变量名到变量值的映射。示例:

    awk 'BEGIN{print ENVIRON["HOME"]}' 
    

    这将打印$HOME的内容

    所以现在你可以这样:

    1. 从字符串创建映射以替换到环境中
    2. 遍历名称:

    这看起来像这样:

    awk 'BEGIN{ map["NAME1"]="ENVIRONMENT_NAME1"
                map["NAME2"]="ENVIRONMENT_NAME2"
                map["NAME3"]="ENVIRONMENT_NAME3" }
         { for(i in map) gsub("/<" i "/>",ENVIRON[map[i]]) }
         { print }' file
    

    与第一个解决方案中的sed 类似,我添加了一种方法来确保字符串NAME1FOO 不会被ENVIRONMENT_NAME1FOO 替换。通过在正则表达式中添加 word_boundaries /&lt;/&gt;

    **注意:此方法可能会创建循环。假设你有一个环境变量:

    ENVIRONMENT_NAME1="NAME2"
    

    那么字符串NAME1可能被替换为ENVIRONMENT_NAME2的内容。我说 可能 因为一切都取决于 for 循环中的横向顺序,这取决于 awk。

    【讨论】:

    • 谢谢,我不能使用“envsubst”,因为我在 docker 镜像中执行此操作,并且我没有更改 docker 镜像来安装“envsubst”
    • @AshikaUmangaUmagiliya 我添加了一个辅助解决方案,它可以很好地解决sed 遇到的换行符或斜杠等问题。
    【解决方案2】:

    要查看变量是如何在sed 命令中展开的:

    set -xv
    sed  -e  "s/JAAS_CONF/$CONNECT_SASL_JAAS_CONFIG/g;" props.txt
    set +xv`
    

    这应该产生类似:

    + sed -e 's/JAAS_CONF/org.apache.kafka.common.security.plain.PlainLoginModule required username="USER" password="XXXX/YYY";/g;' props.txt
    sed: -e expression #1, char 109: unknown option to `s'
    

    嵌入的双引号和正斜杠(在变量中)导致您的问题;正斜杠可以用不同的分隔符来处理(正如@Rachid 指出的那样)。

    双引号可以通过几种方式解决,一个想法:

    $ sed  -e  's|JAAS_CONF|'"${CONNECT_SASL_JAAS_CONFIG}"'|g;' props.txt
    
    # or
    
    $ sed  -e  "s|JAAS_CONF|""${CONNECT_SASL_JAAS_CONFIG}""|g;" props.txt 
    
    # will produce:
    
    sasl.jaas.config = org.apache.kafka.common.security.plain.PlainLoginModule required username="USER" password="XXXX/YYY";
    

    地点:

    • 我们将sed 命令模式分成三部分...`s|JAAS_CONF|' + "${变量}" + '|g;'
    • 对第 1 部分和第 3 部分使用单引号或双引号提供相同的结果(在这种情况下)

    【讨论】:

    • 实际上我意识到 env var 末尾有一个换行符。这可能是“未终止的 `s' 命令”错误的原因
    • 终于找到了解决办法.. sed -e "s|JAAS_CONF|${CONNECT_SASL_JAAS_CONFIG//$'\n'/\n}|g" file.txt
    【解决方案3】:

    您似乎调用了错误的变量名称“CONNECT_CONSUMER_SASL_JAAS_CONFIG”不是您在 echo 命令中显示的内容。 尝试:

    sed "s/JAAS_CONF/$CONNECT_SASL_JAAS_CONFIG/g" props.txt
    

    输出:

    sasl.jaas.config = org.apache.kafka.common.security.plain.PlainLoginModule required username="USER" password="XXXXYYY";
    

    编辑:如果您的字符串中有特殊字符,您可以使用另一个分隔符,如 # 或 ~ 或 |代替 /。它看起来像:

    sed "s#JAAS_CONF#$CONNECT_SASL_JAAS_CONFIG#g" props.txt
    

    【讨论】:

    • 问题中的错字。即使变量名正确,也会出现同样的错误
    • 如果变量包含斜杠,这将失败
    【解决方案4】:

    您确定 $CONNECT_SASL_JAAS_CONFIG 的内容是您所期望的吗?确保您在 $CONNECT_SASL_JAAS_CONFIG 中有正确的内容。因为错误消息中的索引“168”表明您得到的命令行至少包含 168 个字符。但它不应该。

    我可以重现这种错误:

        $ var=xxx/
        $ sed  -e  "s/JAAS_CONF/$var/g;" props.txt
        sed: -e expression #1, char 17: unknown option to `s'
    

    因此,请尝试通过打印变量的内容来确保查看正确的变量,以确保它符合您的预期并使用“{}”保护您的命令行:

         $ sed  -e  "s/JAAS_CONF/${CONNECT_SASL_JAAS_CONFIG}/g;" props.txt
    

    【讨论】:

    • 我屏蔽了用户名和密码。这就是为什么它更短
    • 您的用户名或密码中是否有任何特殊字符(如“/”)可以解释错误?因为如果你在密码中有一个“/”,你就会得到错误。
    • 实际上,是的。我的密码中有“/”
    • 好的。所以这就是它失败的原因。
    • 您可以使用另一个没有出现在名称或密码中的分隔符。例如,使用“|”而不是“/”:sed -e“s|JAAS_CONF|${CONNECT_SASL_JAAS_CONFIG}|g;”道具.txt
    猜你喜欢
    • 1970-01-01
    • 2018-03-24
    • 2023-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2014-01-18
    • 2019-11-29
    相关资源
    最近更新 更多