2

I want to append multiple variables to the end of a line that contains a certain string. Here is my function:

function () { sudo sed -i '/^STRING/ s/$/ '$@'/' FILE; }

However I got sed: -e expression #1, char 24: unterminated `s' command

How can I pass all arguments of this function to sed?

Example:

The file is like:

sometext
sometext STRING sometext
sometext

After I execute the command function test1 test2, the file should be changed to

sometext
sometext STRING sometext test1 test2
sometext
  • 1
    @Kusalananda I know how to pass a single variable to sed, but have no idea what to do with a list of variables – roymaztang Jan 30 '17 at 20:30
  • Could you show what command you are expecting to be executing if you gave this function the arguments XXXX and YYYY? – Kusalananda Jan 30 '17 at 20:33
  • @Kusalananda Yes I updated the description – roymaztang Jan 30 '17 at 20:42
  • 2
    It's easy to see why it doesn't work if you run set -x before that... $@ expands to the positional parameters (and also word splits as it's not quoted) which effectively translates to sed 's/$/ $1' $2 ... $n/ FILE hence the error. Try something like add_user () { s=$@; sed "s/$/$s/" FILE; } – don_crissti Jan 30 '17 at 20:48
1

You aren't appending “multiple variables”. You're appending a string. The most straightforward interface for your function would be to call it with a single string as its argument:

myfunction 'test1 test2'

and then (not using function as the function name because it's a keyword in some shells)

myfunction () {
  sudo sed -i "/^STRING/ s/\$/ $1/" FILE
}

Beware that this doesn't actually append the specified string, because the argument is interpolated into the sed script. Any / or \ in the argument is not interpreted literally. You can work around that by first preparing the argument:

myfunction () {
  extra=$(printf '%s\n' "$1" | sed 's![\\/]!\\&!g')
  sudo sed -i "/^STRING/ s/\$/ $extra/" FILE
}

Alternatively you can use another tool such as perl:

myfunction () {
  sudo env extra="$1" perl -i -pe '/^STRING/ s/$/\Q$ENV{extra}/' FILE
}

If you absolutely want your function to take a series of strings as arguments, and append them all in order with a space in between, then you can use "$*". This expands to a single word containing all the arguments of the function with a space in between.

myfunction () {
  extra=$(printf '%s\n' "$*" | sed 's![\\/]!\\&!g')
  sudo sed -i "/^STRING/ s/\$/ $extra/" FILE
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.