9

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 contain special characters that could brake regex. How can i escape all of the possible special characters in $data_line before i execute sed command?

1

4 Answers 4

6

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!"
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Dennis for the detailed answer. I will mark it as my accepted answer, because it gives the answer to what I asked in my question. But I will use Ignacio technique because it does what i need in much cleaner way IMO.
The third line could be char=${candidates//[$data_line]} instead of using echo and tr.
6
grep -v -F "$data_line" "$data_dir" > ...

1 Comment

Could you explain this a little bit?
0

It's an old question, but for those still coming here, sed allows you to use a delimiter other than the forward slash.

For my script I switched from sed -i 's/$OLD_URL/$NEW_URL/g' to sed -i 's|$OLD_URL|$NEW_URL|g', as my URLs contained forward slashes, but not pipes.

Comments

0

# Source - https://stackoverflow.com/a/2933544
# Posted by Ignacio Vazquez-Abrams
# Retrieved 2025-11-07, License - CC BY-SA 2.5

grep -v -F "$data_line" "$data_dir" > ...

-v removes lines that match

-F uses string as is, special characters used without being special

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.