5

I want to enable some configurations only when the distribution is Fedora. Here is my code.

let s:os = system("sed -n 's/^NAME=\(.*\)/\1/p' /etc/os-release")
echo s:os
if s:os == "Fedora"
        " some configurations
endif

This snippet doesn't work and the s:os is an empty string. However, the sed command works well when I run it in shell directly. I don't know why it doesn't work in vimrc.

2
  • 4
    Double all backslashes or switch to using single-quoted strings.
    – Matt
    Commented Dec 24, 2019 at 14:33
  • 1
    @Matt Many thanks. Save my life!
    – haolee
    Commented Dec 24, 2019 at 15:08

2 Answers 2

2

The trouble you're having is with the backslashes inside the string (as @Matt correctly pointed out in the comments.)

Vim strings (using double-quotes as delimiters) interpret the backslash as a special character, so you need to escape them with an additional backslash if you want to use them in a double-quoted string.

let s:os = system("sed -n 's/^NAME=\\(.*\\)/\\1/p' /etc/os-release")

Alternatively, you might want to use single-quoted strings in Vim, since those do not treat the backslash as special and don't require escaping it. This is pretty fine in this particular case, since using double-quotes for the sed expression in the shell command is OK, since they do not contain any shell metacharacters such as $:

let s:os = system('sed -n "s/^NAME=\(.*\)/\1/p" /etc/os-release')

On the other hand, you could actually do that same operation using Vimscript primitives only, which should be more efficient (since you're not spawning a couple of external processes anymore) and more portable (since it doesn't depend on which particular shell you're using or whether a sed can even be found in $PATH.)

Consider using the following snippet instead:

let s:os = matchlist(readfile('/etc/os-release'), '^NAME=\(.*\)')[1]

See :help readfile() and :help matchlist().

You might want to add some error handling, in case the file doesn't exist or the variable match can't be found there.

3

@Matt is absolutely right; you might use double backslashes:

let s:os = system("sed -n 's/^NAME=\\(.*\\)/\\1/p' /etc/os-release")

or switch to a single-quoted string:

let s:os = system('sed -n "s/^NAME=\(.*\)/\1/p" /etc/os-release')

But here's a tidbit: Here documents are also available as of vim 8.1.1362:

let s:command =<< trim END
    sed -n "s/^NAME=\(.*\)/\1/p" /etc/os-release
END
let s:os = system(s:command[0])

See :help :let-heredoc for more information.

Happy Vimming!

Your Answer

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

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