Search code examples
regexbashsedescaping

Escape characters contained by bash variable in regex pattern


In my bash script, i am trying to execute following Linux command:

sed -i "/$data_line/ d" $data_dir

$data_line is entered by user and it may conatain special characters that could brake regex. How can i escape all of the possible special characters in $data_line before i execute sed command?


Solution

  • You might be able to use this technique to protect the selector. The lines marked with "*****" below are the significant lines. The others are mostly for testing and demonstration. The key is to use a character that doesn't appear in the user input to delimit the selector address.

    data_line='.*/ s/GOLD/LEAD/g;b;/.*'    # scary user input
    candidates='/:.|@#%^&;,!~abcABC'       # *****   # (make it as long as you like)
    char=$(echo "$candidates" | tr -d "$data_line")    # *****
    char=${char:0:1}   # ***** choose the first candidate that doesn't appear in the user input
    
    if [ -z "$char" ]    # ***** this test checks for exhaustion of the candidate character set
    then
        echo "Unusable user input. Recommendation: cigarette and blindfold."
        exit 1
    fi
    
    # test without protection
    excitement="GOLD, I tell you, thar's GOLD in them thar hills!" 
    echo "$excitement" | sed "/$data_line/ d"
    # output: "LEAD, I tell you, thar's LEAD in them thar hills!"
    
    # test WITH protection
    echo "$excitement" | sed "\\${char}${data_line}${char} d"    # *****
    # output: "GOLD, I tell you, thar's GOLD in them thar hills!"
    
    # test WITH protection and useful user input
    data_line="secret"
    mystery="The secret map is tucked in a hidden compartment in my saddle bag."
    echo -e "$excitement\n$mystery" | sed "\\${char}${data_line}${char} d"
    # output: "GOLD, I tell you, thar's GOLD in them thar hills!"