0

From the output of:

$ pyenv virtualenvs

I want to extract with sed the names of the virtual environments as well their path. The same for the default environment is marked with an asterisk. The results look like this:

 3.6.3/envs/venv_1 (created from /home/user/.pyenv/versions/3.6.3)
* anaconda3-5.0.0 (created from /home/user/.pyenv/versions/anaconda3-5.0.0)
 venv_py3.6.3__test_01 (created from /home/user/.pyenv/versions/3.6.3)

With PCRE as FLAVOR:

^\*\s([a-zA-Z0-9\.\-]*)\s\(created\sfrom\s([a-zA-Z0-9\.\-\/]*)

I can capture both groups without problem:

Group 1: anaconda3-5.0.0

Group 2: /home/user/.pyenv/versions/anaconda3-5.0.0

(tested on https://regex101.com)

but I cannot make it work with sed.

What I've managed so far is e.g. for the default environment to extract the name with:

sed -e 's/^\*\s\(.*\)\s(created\(.*\)/\1/

anaconda3-5.0.0

but for the path I get with:

sed -e 's/^\*\s\(.*\)\s(created\sfrom\s\(.*\)/\2/' 

/home/user/.pyenv/versions/anaconda3-5.0.0)

namely there is also a parenthesis at the right end. I know this is not the correct approach but I couldn't make it better so far.

Any ideas how can make it work with sed?

UPDATE:

As of now I have this:

for the names:

$ pyenv virtualenvs | sed -r 's/\(created\s*from\s*//g;s/\)//g;s/^\s*//g' | awk '{print $1}'

for the paths:

$ pyenv virtualenvs | sed -r 's/\(created\s*from\s*//g;s/\)//g;s/^\s*//g' | awk '{print $2}'
1

I'd use a simple perl oneliner:

Given:

cat file
 3.6.3/envs/venv_1 (created from /home/user/.pyenv/versions/3.6.3)
* anaconda3-5.0.0 (created from /home/user/.pyenv/versions/anaconda3-5.0.0)
 venv_py3.6.3__test_01 (created from /home/user/.pyenv/versions/3.6.3)

Running:

cat file | perl -ane 'print "$1\n$2\n" if m#^\*?\h+(\S+)\h+\(created from ([\w/.-]+)#'
3.6.3/envs/venv_1
/home/user/.pyenv/versions/3.6.3
anaconda3-5.0.0
/home/user/.pyenv/versions/anaconda3-5.0.0
venv_py3.6.3__test_01
/home/user/.pyenv/versions/3.6.3

Of course, replace cat file with pyenv virtualenvs

Regex explanation:

m#                      : match, regex delimiter
    ^                   : beginning of line
      \*?               : an optional asterisk
      \h+               : 1 or more horizontal spaces (i.e. space or tab)
      (\S+)             : group 1, 1 or more non space characters
      \h+               : 1 or more horizontal spaces (i.e. space or tab)
      \(created from    : literally
      ([\w/.-]+)        : group 2, 1 or more word char, slash, dot, minus
#                       : regex delim
  • Thanks. I can get the default name and path with this, but how about the others? – coverflower Feb 15 at 16:21
  • @coverflower: Sorry I didn't well understand. See my edit edit, is it OK? – Toto Feb 15 at 16:32
  • 2
    The advantage of this is that Perl regexes actually are PCRE, as in the original test, while sed's POSIX Basic regular expressions are far away from that. – grawity Feb 15 at 16:59
  • You might have issues with paths that use other characters... the following regex is probably more forgiving: ^\*? (.*?) \(created from (.*?)\)$ – Attie Feb 15 at 18:39

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.