Draqun
Draqun

Reputation: 364

sed does not work properly when pattern comes from variable

I have question. Why sed does not work properly when pattern comes from bash variable? I prepared simple bash script to show it for you. There is some known reason why this happen?

#!/usr/bin/env bash

file=/tmp/egz.txt

# Creating example file
echo "First Line" > $file
echo "Second line" >> $file
echo "Third Line" >> $file
echo "Some other line" >> $file

sed_pattern="s|Some other line|Fourth Line|g"

sed -i "s|Some other line|Fourth Line|g" $file

if [[ $? -eq 0 ]]; then
    echo "Sed with pattern works properly."
else
    echo "Sed with pattern works incorrect."
fi

sed -i $sed_pattern $file

if [[ $? -eq 0 ]]; then
    echo "Sed with pattern from variable works properly."
else
    echo "Sed with pattern from variable works incorrect."
fi

On last Ubuntu result of this script is looks like this

Sed with pattern works properly.
sed: -e expression #1, char 6: undeterminated `s' command
Sed with pattern from variable works incorrect.

Upvotes: 0

Views: 67

Answers (3)

Cong Ma
Cong Ma

Reputation: 11302

The reason is that unquoted expansion of variable sed_pattern results in a shell command with arguments separated by the space character

In effect the second invocation of sed is like

sed -i s|Some other line|Fourth Line|g [... rest of cmdline...]

And in this cmdline the arguments are sed, -i, s|Some, other, line|Fourth, Line|g, and others. The error message refers to the s|Some part where the s expression is incomplete after the 6th character (the exact error message depends on how the implementation of sed attempts to decipher the garbled command).

Always use quotes.

Upvotes: 0

slashcool
slashcool

Reputation: 178

That's because SED doesn't know he must interpret the variable. Also, prefer simple quotes for your variable, to avoid the pipe being interpreted.

You can modify your code as:

#!/usr/bin/env bash

file=/tmp/egz.txt

# Creating example file
echo "First Line" > $file
echo "Second line" >> $file
echo "Third Line" >> $file
echo "Some other line" >> $file

sed_pattern='s|Some other line|Fourth Line|g'

sed -i "s|Some other line|Fourth Line|g" $file

if [[ $? -eq 0 ]]; then
    echo "Sed with pattern works properly."
else
    echo "Sed with pattern works incorrect."
fi

sed -i "$sed_pattern" $file

if [[ $? -eq 0 ]]; then
    echo "Sed with pattern from variable works properly."
else
    echo "Sed with pattern from variable works incorrect."
fi

Upvotes: 1

sahaquiel
sahaquiel

Reputation: 1838

Use quotes near $sed_pattern variable.

#!/usr/bin/env bash

file=/tmp/egz.txt

# Creating example file
echo "First Line" > $file
echo "Second line" >> $file
echo "Third Line" >> $file
echo "Some other line" >> $file

sed_pattern="s|Some other line|Fourth Line|g"

sed -i "s|Some other line|Fourth Line|g" $file

if [[ $? -eq 0 ]]; then
    echo "Sed with pattern works properly."
else
    echo "Sed with pattern works incorrect."
fi

sed -i "${sed_pattern}" $file

if [[ $? -eq 0 ]]; then
    echo "Sed with pattern from variable works properly."
else
    echo "Sed with pattern from variable works incorrect."
fi

Output:

Sed with pattern works properly.
Sed with pattern from variable works properly.

Upvotes: 1

Related Questions