Replace/substitute adversarial substring variables in shell script

后端 未结 1 1394
谎友^
谎友^ 2021-01-25 10:32

I have three unescaped adversarial shell variables.

$mystring
$old
$new

Remember, all three strings are adversarial. They will contain special

相关标签:
1条回答
  • 2021-01-25 10:58

    There's nothing fancy here -- the only thing you need to do to ensure that your values are treated as literals in a parameter expansion is to ensure that you're quoting the search value, as described in the relevant section of BashFAQ #21:

    result=${mystring/"$old"/$new}
    

    Without the double quotes on the inside, $old would be interpreted as a fnmatch-style glob expression; with them, it's literal.


    To operate on streams instead, consider gsub_literal, also described in BashFAQ #21:

    # usage: gsub_literal STR REP
    # replaces all instances of STR with REP. reads from stdin and writes to stdout.
    gsub_literal() {
      # STR cannot be empty
      [[ $1 ]] || return
    
      # string manip needed to escape '\'s, so awk doesn't expand '\n' and such
      awk -v str="${1//\\/\\\\}" -v rep="${2//\\/\\\\}" '
        # get the length of the search string
        BEGIN {
          len = length(str);
        }
    
        {
          # empty the output string
          out = "";
    
          # continue looping while the search string is in the line
          while (i = index($0, str)) {
            # append everything up to the search string, and the replacement string
            out = out substr($0, 1, i-1) rep;
    
            # remove everything up to and including the first instance of the
            # search string from the line
            $0 = substr($0, i + len);
          }
    
          # append whatever is left
          out = out $0;
    
          print out;
        }
      '
    }
    
    some_command | gsub_literal "$search" "$rep"
    

    ...which can also be used for in-place replacement on files using techniques from the following (yet again taken from the previously-linked FAQ):

    # Using GNU tools to preseve ownership/group/permissions
    gsub_literal "$search" "$rep" < "$file" > tmp &&
      chown --reference="$file" tmp &&
      chmod --reference="$file" tmp &&
      mv -- tmp "$file"
    
    0 讨论(0)
提交回复
热议问题