添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
小胡子的石榴  ·  python ...·  1 年前    · 

我在教程中读到,要从shell中替换环境变量,你需要停止,并 "引出" $varname 部分,这样它就不会被直接替换,这就是我所做的,而这只有在变量紧接着被定义的情况下才有效。

如何让sed识别 $var 作为一个环境变量,因为它是在shell中定义的?

4 个评论
$PWD包含一个/,这是结束替代命令。
@derobert: tnx.其中一个解决方案解决了这个问题...
在shell中使用 set -x ,可以让shell在执行每条命令之前回声。这可以消除很多困惑。(另外,我经常使用 set -u 来使去引用未设置的变量成为一个硬错误。(也请看 set -e )。
我希望找到一种方法,让sed处理环境变量,以免将数值泄露到进程表中,根据这个主题中的所有答案,sed似乎是安装秘密的错误工具。
linux
unix
shell
sed
RomanM
RomanM
发布于 2009-02-25
12 个回答
Norman Ramsey
Norman Ramsey
发布于 2022-08-30
已采纳
0 人赞同

你的两个例子看起来是一样的,这使得问题难以诊断。 潜在的问题。

  • 你可能需要双引号,如: sed 's/xxx/'"$PWD"'/'

  • 替换代码1】可能包含一个斜线,在这种情况下,你需要找到一个字符 not 包含在 $PWD 中,作为分隔符使用。

  • 要同时解决这两个问题,也许

    sed 's@xxx@'"$PWD"'@'
        
    但是,那么我可以使用什么字符,我知道肯定不会出现在路径名称中?
    你可以有几个像@#%!这样的候选者,用case表达式来检查$PWD是否有它们。 例如,case "$PWD" of @ ) ;; *) delim="@" ;; esac; 重复,直到$delim不是空的。
    还有一个替代方法,而不是使用双引号。见我的 答案 below.
    你可以为sed使用另一个分隔符。你不需要使用/,你也可以使用 ,如果你的环境变量是一个url。
    如果字符串中包含一个n后面的字母--如何阻止sed将其转换为一个换行符呢?
    Jeach
    Jeach
    发布于 2022-08-30
    0 人赞同

    除了Norman Ramsey的回答之外,我还想补充一点,你可以对整个字符串进行双引号(这可能会使语句更易读,不容易出错)。

    因此,如果你想搜索'foo',并用$BAR的内容来替换它,你可以将sed命令放在双引号中。

    sed 's/foo/$BAR/g'
    sed "s/foo/$BAR/g"
    

    在第一种情况下,$BAR不会正确展开,而在第二种情况下,$BAR会正确展开。

    这比乱用双引号、单引号等要干净。
    这是我为了让环境变量在这个命令中正确展开而不得不使用的方法: sed -i "s/127.0.0.1/127.0.0.1 localhost $HOSTNAME/" hosts
    mjp
    这很好,但当你想做一些更复杂的替换时,它就不起作用了,比如 "2,$s/^/$foo/" ,因为 $s 也会被解释成一个变量,而它不应该被解释。
    MoRe
    这一点并不奏效,因为我仍然需要一个不同的路径分隔符,就像其他答案建议的那样。
    @mjp,你所说的是正确的,但我认为可以写成 "2,$ s/^/$foo/"
    Thales Ceolin
    Thales Ceolin
    发布于 2022-08-30
    0 人赞同

    另一个简单的选择。

    由于 $PWD 通常会包含一个斜线 / ,所以使用 | 而不是 / 作为sed语句。

    sed -e "s|xxx|$PWD|"
        
    你说 "替代使用双引号",但你的例子却使用了双引号?
    我想重点是它没有直接在 $PWD 周围使用双引号...?
    很干净的模式,但这里不需要-e(--表达式),因为这个例子不是把几个表达式串在一起。
    使用|比使用/更好,因为我的变量中的一些值有特殊字符,如预览:1.2.7-2208.190204。
    Paulo Fidalgo
    Paulo Fidalgo
    发布于 2022-08-30
    0 人赞同

    除了"/",你还可以在替换中使用其他字符。

    sed "s#$1#$2#g" -i FILE
        
    在我的具体案例中,2美元是一个文件路径,所以 sed 由于解释了2美元内容中的 / 而出现了问题。 谢谢你的建议。
    0 人赞同

    一. bad way: change delimiter

    sed 's/xxx/'"$PWD"'/'
    sed 's:xxx:'"$PWD"':'
    sed 's@xxx@'"$PWD"'@'
    

    也许这些不是最终的答案。

    你不可能知道在$PWD中会出现什么字符,/中会出现什么字符。:。或@
    如果$PWD中的分隔符,它们将破坏表达式。

    好的方法是替换(逃避)$PWD中的特殊字符。

    二. good way: escape delimiter

    尝试将URL替换为$url(内容中有:/)。

    x.com:80/aa/bb/aa.js
    

    in string $tmp

    <a href="URL">URL</a>
    

    A. use / as delimiter

    /作为\/在var中转义(在sed表达式中使用前)。

    ## step 1: try escape
    echo ${url//\//\\/}
    x.com:80\/aa\/bb\/aa.js   #escape fine
    echo ${url//\//\/}
    x.com:80/aa/bb/aa.js      #escape not success
    echo "${url//\//\/}"
    x.com:80\/aa\/bb\/aa.js   #escape fine, notice `"`
    ## step 2: do sed
    echo $tmp | sed "s/URL/${url//\//\\/}/"
    <a href="x.com:80/aa/bb/aa.js">URL</a>
    echo $tmp | sed "s/URL/${url//\//\/}/"
    <a href="x.com:80/aa/bb/aa.js">URL</a>
    

    B. use : as delimiter (more readable than /)

    :作为\:在var中转义(在sed表达式中使用前)。

    ## step 1: try escape
    echo ${url//:/\:}
    x.com:80/aa/bb/aa.js     #escape not success
    echo "${url//:/\:}"
    x.com\:80/aa/bb/aa.js    #escape fine, notice `"`
    ## step 2: do sed
    echo $tmp | sed "s:URL:${url//:/\:}:g"
    <a href="x.com:80/aa/bb/aa.js">x.com:80/aa/bb/aa.js</a>
        
    Eddie
    Eddie
    发布于 2022-08-30
    0 人赞同

    通过你的问题编辑,我看到了你的问题。 假设当前目录是 /home/yourname ......在这种情况下,你的命令如下。

    sed 's/xxx/'$PWD'/'
    
    sed `s/xxx//home/yourname//
    

    这是不有效的。 如果你想这样做,你需要在$PWD中的每个\前面加上一个/字符。

    but PWD is defined by the shell ... if i go echo $PWD i get the pwd
    那么,你如何逃避环境变量?
    所选答案描述了一种变通方法......不要使用斜线作为分隔符。
    一旦你的当前工作目录包含那个其他字符,这将成为一个问题。
    adeger
    adeger
    发布于 2022-08-30
    0 人赞同

    实际上,最简单的事情(至少在GNU sed中)是为sed替换( s )命令使用一个不同的分隔符。 因此,与其将 s/pattern/'$mypath'/ 扩展为 s/pattern//my/path/ ,当然会混淆 s 命令,不如使用 s!pattern!'$mypath'! ,它将被扩展为 s!pattern!/my/path! 。我使用了bang( ! )字符(或者使用任何你喜欢的东西),这避免了通常的,但由不得你唯一选择的正斜线作为分隔符。

    Mamadou Lamine Diatta
    Mamadou Lamine Diatta
    发布于 2022-08-30
    0 人赞同

    在sed中处理VARIABLES

    [root@gislab00207 ldom]# echo domainname: None > /tmp/1.txt
    [root@gislab00207 ldom]# cat /tmp/1.txt
    domainname: None
    [root@gislab00207 ldom]# echo ${DOMAIN_NAME}
    dcsw-79-98vm.us.oracle.com
    [root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: ${DOMAIN_NAME}/g'
     --- Below is the result -- very funny.
    domainname: ${DOMAIN_NAME}
     --- You need to single quote your variable like this ... 
    [root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: '${DOMAIN_NAME}'/g'
    --- The right result is below 
    domainname: dcsw-79-98vm.us.oracle.com
        
    我在Azure DevOps的YAML管道中苦苦挣扎,想让它发挥作用。这条评论帮助我成功地使用这个技巧来标记一些配置文件。
    PsychoData
    PsychoData
    发布于 2022-08-30
    0 人赞同
    VAR=8675309
    echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
    sed 's/:[0-9]*:/:'$VAR':/1' 
    

    其中VAR包含你想要替换的字段。

    aniskop
    aniskop
    发布于 2022-08-30
    0 人赞同

    我也有类似的问题,我有一个列表,我必须根据模板(包含 @INPUT@ 的元素)建立一个SQL脚本。

    for i in LIST 
        awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
        
    Joseph Sturtevant
    Joseph Sturtevant
    发布于 2022-08-30
    0 人赞同

    如果你的替换字符串可能包含其他 sed控制字符 ,然后进行两步替换(首先是 对替换字符串进行转义 )可能是你想要的。

    PWD='/a\1&b$_' # these are problematic for sed
    PWD_ESC=$(printf '%s\n' "$PWD" | sed -e 's/[\/&]/\\&/g')
    echo 'xxx' | sed "s/xxx/$PWD_ESC/" # now this works as expected
        
    Andreas Panagiotidis
    Andreas Panagiotidis
    发布于 2022-08-30
    0 人赞同

    对我来说,用sed替换文件中的环境变量值的一些文本,只对配额起作用,如下所示。

    sed -i 's/original_value/'"$MY_ENVIRNONMENT_VARIABLE"'/g' myfile.txt