【问题标题】:Search and replace variables in a file using bash/sed使用 bash/sed 搜索和替换文件中的变量
【发布时间】:2012-03-29 15:24:31
【问题描述】:

我正在尝试编写一个 bash 脚本(script.sh)来搜索和替换 input.sh 文件中的一些变量。但我只需要修改 variable_list 文件中存在的变量,其他变量保持原样。

变量列表

${user}  
${dbname}

input.sh

username=${user}  
password=${password}  
dbname=${dbname}

预期的输出文件

username=oracle  
password=${password} > This line won't be changed as this variable(${password}) is not in variable_list file
dbname=oracle

以下是我尝试使用的脚本,但我找不到正确的 sed 表达式

script.sh

export user=oracle  
export password=oracle123  
export dbname=oracle

variable='variable_list'  
while read line ;  
do  
 if [[ -n $line ]]     
 then  
  sed -i 's/$line/$line/g' input.sh > output.sh  
 fi  
done < "$variable"    

【问题讨论】:

    标签: bash sed


    【解决方案1】:

    这可行:

    #!/bin/bash
    
    export user=oracle  
    export password=oracle123  
    export dbname=oracle
    
    variable='variable_list'  
    while read line ;  
    do  
     if [[ -n $line ]]
     then
      exp=$(sed -e 's/\$/\\&/g' <<< "$line")
      var=$(sed -e 's/\${\([^}]\+\)}/\1/' <<< "$line")
      sed -i "s/$exp/${!var}/g" input.sh
     fi  
    done < "$variable"
    

    第一个sed 表达式转义了作为正则表达式元字符的$。第二个仅提取变量名,然后我们使用间接获取当前 shell 中的值并在 sed 表达式中使用它。

    编辑

    与其多次重写文件,这样做可能更有效,为sed构建参数列表:

    #!/bin/bash
    
    export user=oracle  
    export password=oracle123  
    export dbname=oracle
    
    while read var
    do
        exp=$(sed -e 's/\$/\\&/g' <<< "$var")
        var=$(sed -e 's/\${\([^}]\+\)}/\1/' <<< "$var")
        args+=("-e s/$exp/${!var}/g")
    done < "variable_list"
    
    sed "${args[@]}" input.sh > output.sh
    

    【讨论】:

      【解决方案2】:
      user=oracle  
      password=oracle123  
      dbname=oracle
      
      variable_list=( '${user}' '${dbname}' )
      
      while IFS="=$IFS" read variable value; do
          for subst_var in "${variable_list[@]}"; do
              if [[ $subst_var = $value ]]; then
                  eval "value=$subst_var"
                  break
              fi
          done
          printf "%s=%s\n" "$variable" "$value"
      done < input.sh > output.sh
      

      【讨论】:

        【解决方案3】:

        这是一个有效的 script.sh:

        #!/bin/bash
        
        user=oracle
        password=oracle123
        dbname=oracle
        
        variable='variable_list'
        text=$(cat input.sh)
        while read line
        do
          value=$(eval echo $line)  
          text=$(sed "s/$line/$value/g" <<< "$text")
        done < "$variable"
        echo "$text" > output.sh
        

        请注意,您的原始版本在 sed 字符串周围包含单引号,它不会插入 $line 的值。它试图在$ 行的末尾寻找文字line(永远找不到任何东西)。

        由于您要在 $line 中查找变量的值,因此您需要执行 eval 来获取它。

        另外,由于您要循环多个变量,中间的text 变量会在循环时存储结果。

        export 关键字在此脚本中也是 unnecessary,除非它被用于某些未显示的子流程。

        【讨论】:

          【解决方案4】:

          TXR 解决方案。动态构建过滤器。过滤器在内部实现为 trie 数据结构,它为我们提供了一个类似lex 的状态机,它在扫描输入时立即匹配整个字典。为简单起见,我们将${} 作为变量名的一部分。

          @(bind vars (("${user}" "oracle")
                       ("${dbname}" "oracle")
                       ("${password}" "letme1n")))
          @(next "variable_list")
          @(collect)
          @entries
          @(end)
          @(deffilter subst . @(mapcar (op list @1 (second [find vars @1 equal first]))
                                       entries))
          @(next "input.sh")
          @(collect)
          @line
          @  (output :filter subst)
          @line
          @  (end)
          @(end)
          

          运行:

          $ txr subst.txr
          username=oracle
          password=${password}
          dbname=oracle
          

          input.sh:(如给定)

          username=${user}
          password=${password}
          dbname=${dbname}
          

          variable_list:(如给定)

          ${user}
          ${dbname}
          

          【讨论】:

          • (mapcar (op list @1 (second [find vars @1 equal first])) entries) 的意思是“通过一个函数映射entries 的元素,该函数形成一个由变量组成的二元素列表,以及在var 列表中替换该变量的结果。” [find vars @1 equal first] 表示在vars 中查找匿名函数(条目)的参数1,使用equal 作为比较(与字符串一起使用),并使用每个条目的first 作为键(因为条目是两个-元素列表,第一个是键)。 find 返回该对,因此 (second ...) 获取值。
          猜你喜欢
          • 2014-06-08
          • 2017-08-02
          • 2014-09-08
          • 2011-12-02
          • 2021-11-20
          • 1970-01-01
          • 2011-08-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多