mikeb
mikeb

Reputation: 11267

sed replace using shell variables

I'm on Linux Mint 17

I got this command looking at other sed questions on here, but can't seem to get it to work. Can anyone suggest what is wrong here? This seems pretty simple but won't work:

$ cat t | sed "s/${FSTAB_UUID}/${SWAP_UUID}/"

sed: -e expression #1, char 2: unterminated `s' command

$ echo $FSTAB_UUID

15542fac-468c-405f-a156-dd781ece7568

$ echo $SWAP_UUID

2891fb61-26c3-4606-b310-6c12e4788db5

$ cat t

UUID=accbd859-7cdd-4d00-86ea-2b5d7d1cee75 /     ext4  errors=remount-ro 0 1
UUID=15542fac-468c-405f-a156-dd781ece7568 none  swap  rw 0 0

Upvotes: 0

Views: 475

Answers (2)

zezollo
zezollo

Reputation: 5017

With your code, I get a similar (only) error on Linux (bash 4.3.11 GNU sed 4.2.2):

$ FSTAB_UUID=15542fac-468c-405f-a156-dd781ece7568
$ SWAP_UUID=2891fb61-26c3-4606-b310-6c12e4788db5
$ cat t |  sed "s/${FSTAB_UUID}/${SWAP_UUID}/"
sed: -e expression n°1, caractère 0: pas d'expression régulière précédente

(translation: sed: -e expression #1, character 0: no previous regular expression)

But not on FreeBSD (10.2-RELEASE). I can't tell why, and can't find anything explaining this in relation to a difference between GNU sed and classic sed.

Now, on my Linux box, while this may not be the most beautiful workaround, and despite the fact the behaviour shouldn't be different from your code, this has yet worked to get the expected result:

$ cat t |  sed 's/'"${FSTAB_UUID}"'/'"${SWAP_UUID}"'/'
UUID=accbd859-7cdd-4d00-86ea-2b5d7d1cee75 /     ext4  errors=remount-ro 0 1
UUID=2891fb61-26c3-4606-b310-6c12e4788db5 none  swap  rw 0 0
$ cat t
UUID=accbd859-7cdd-4d00-86ea-2b5d7d1cee75 /     ext4  errors=remount-ro 0 1
UUID=15542fac-468c-405f-a156-dd781ece7568 none  swap  rw 0 0
$ 

(just keep the sed parts in simple quotes and put the variables between double quotes).

Upvotes: 0

John Bollinger
John Bollinger

Reputation: 180048

I can reproduce your problem by ensuring that the value of $FSTAB_UUID starts with a newline (as suggested by @StefanHegny):

$ FSTAB_UUID="
> 15542fac-468c-405f-a156-dd781ece7568"
$ echo $FSTAB_UUID
15542fac-468c-405f-a156-dd781ece7568
$ echo ">>>$FSTAB_UUID<<<"
>>>
15542fac-468c-405f-a156-dd781ece7568<<<
$ sed "s/${FSTAB_UUID}/${SWAP_UUID}/" t
sed: -e expression #1, char 2: unterminated `s' command

(Note that the leading > on the second line is a secondary prompt emitted by bash; it is not part of the input.) I see no other explanation for the behavior.

The best solution is to set the values for $FSTAB_UUID and $SWAP_UUID in a way that does not introduce leading or trailing newlines. I can't be any more specific, because it's unclear how they are getting in in the first place.

If you can't keep the newlines out, then you also have the option of taking them out after the fact. This is a bit ugly, but it will remove all leading and trailing whitespace, including newlines, from both values:

FSTAB_UUID=${FSTAB_UUID##+([[:space:]])}
FSTAB_UUID=${FSTAB_UUID%%+([[:space:]])}
SWAP_UUID=${SWAP_UUID##+([[:space:]])}
SWAP_UUID=${SWAP_UUID%%+([[:space:]])}

The ## and %% inside the parameter expansions tell bash to trim the longest prefix or suffix, respectively, that matches the following pattern. For its part, the pattern matches a string of any positive number of whitespace characters.

Upvotes: 1

Related Questions