Como usar a saída do grep como um caminho para o cd?

9

Como posso canalizar grep output como um argumento para o comando cd ?

Por exemplo:

[root@xxx xxx]# pip install django | grep '/usr.*'  
Requirement already satisfied (use --upgrade to upgrade): django in   /usr/lib64/python2.7/site-packages

Aqui /usr/lib64/python2.7/site-packages está destacado e quero passar essa sequência para cd .

    
por micgeronimo 23.04.2015 / 23:19

2 respostas

16

Use a substituição de comandos do Bash $() , você também precisa de -o com grep para selecionar apenas a parte correspondente:

cd "$(pip install django | grep -o '/usr.*')"

Note que, embora você vá embora neste caso, você deve sempre incluir a substituição de comandos com aspas duplas, para que o shell não execute divisão de palavras em espaços em branco (por espaço padrão, aba e nova linha, depende da variável IFS no caso de bash ).

    
por heemayl 23.04.2015 / 23:30
9

Dependendo do que você faz e não sabe de antemão sobre o que pip produzirá, você pode decidir grep para algo diferente de /usr.* .

Se você souber que o diretório começa com /usr (e que aparece no final da linha de saída de pip e que /usr não aparece em nenhum lugar na linha antes do nome do diretório), então essa é uma boa escolha; a resposta do heemayl diz-lhe como.

Se a razão você sabe que começa com /usr é que você acabou de executar o comando e sabe o diretório que você deseja alterar, sugiro a solução mais simples de executar o comando cd /usr/lib64/python2.7/site-packages . Isso é menos digitação, mesmo que você não faça uso da conclusão da guia .

Caso contrário, você pode escolher um regexp diferente dependendo do que você sabe sobre a saída sendo analisada. Todas as alternativas abaixo ainda assumem que o nome do diretório aparece no final da linha, mas as outras suposições variam.

Se você souber que o nome do diretório é absoluto (isto é, começa com / ) e nenhum / aparece na linha antes do nome do diretório , pode usar o mesmo regexp que na resposta do heemayl mas com / em vez de /usr :

cd "$(pip install django | grep -o '/.*')"

Corresponde a / seguido de zero ou mais ( * ) de qualquer caractere ( . ).

Se você souber que o nome do diretório não contém espaço em branco horizontal (sem espaços ou tabulações) e aparece no final da linha , você pode usar:

cd "$(pip install django | grep -oP '[^\h]+$')"

Aqui eu usei um regexp Perl ( -P ) porque a abreviação \h (para [:blank:] ) facilita a digitação e a leitura de uma equivalente regexp estendida ( -E ). Isso corresponde a um ou mais ( + ) de qualquer caractere em uma classe de caracteres ( [ ] ) que não é ( ^ ) um espaço ou tabulação ( \h ) .

Se você sabe que ele nome do diretório é imediatamente precedido por in cercado por espaço em branco horizontal (ou seja, preenchido à esquerda e à direita com espaços em branco), e a única ocorrência desse tipo de in na linha , você pode usar:

cd "$(pip install django | grep -oP '\hin\h+\K.+')"

Isso usa uma asserção de look-behind positiva de largura zero ( \K ) para corresponder a um ou mais caracteres ( .+ ) que aparecem após um espaço ou tabulação ( \h ), in e outro ou mais espaços ou tabulações ( \h+ ), sem incluir realmente in e os espaços em branco que o rodeiam no jogo. Declarações de look-around são uma característica das expressões regulares do Perl.

O padrão \h+in\h+\K.+ teria funcionado também, mas precisamos procurar apenas um espaço em branco antes de in , independentemente de quantos estão presentes. Em contraste, devemos combinar todos os espaços em branco após in , ou eles não seriam descartados por \K e eles seriam correspondidos como parte do nome do diretório.

Se você souber que o nome do diretório é imediatamente precedido pela última ocorrência da linha de in seguido por espaço em branco horizontal , você pode usar:

set +H
cd "$(pip install django | grep -oP '\hin\h+(?!.*\hin\h.*)\K.*')"
set -H

Lá, a afirmação de look-behind positiva de largura zero contém uma asserção de look-ahead negativa de largura zero ( (?! ) ).

O ! aparece de modo a ser difícil escapar elegantemente; o método que usei para impedir que ele acionasse a expansão do histórico antes de ser passado para grep é desabilitar temporariamente a expansão do histórico ( set +H ) antes de executar o comando e reativá-lo ( set -H ) posteriormente. Se você estiver usando isso em um script e seu script não contiver set -H , não será necessário fazer isso, já que a expansão do histórico é ativada automaticamente somente quando um shell é executado interativamente.

Por fim, note que nenhuma delas, nem a resposta do heemayl , estão realmente direcionando a saída de grep para cd (embora a saída de pip ainda esteja sendo canalizada para grep ). Em vez de usar canais , a ferramenta apropriada para esse trabalho é command substitution .

    
por Eliah Kagan 24.04.2015 / 01:47