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.

haolee
  • 275
  • 2
  • 6

2 Answers2

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!

Jair López
  • 1,854
  • 1
  • 15
  • 24
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.

guntbert
  • 1,245
  • 1
  • 13
  • 27
filbranden
  • 28,785
  • 3
  • 26
  • 71