Extraindo diretórios de bibliotecas de uma variável longa

2

Eu declarei uma longa variável contendo as bibliotecas para usar durante a compilação:

export LIBS="-L/usr/lib -lcurl -L/lib -lhdf5 -Wl,-rpath,/lib -L/usr/lib64 -lglpk -Wl,-rpath,/usr/local/tools/vtk-6.1.0/lib -L/usr/local/tools/vtk-6.1.0/lib -lvtkIOCore-6.1 -lvtkCommonCore-6.1 -lvtkCommonDataModel-6.1 -lvtkFiltersCore-6.1 -lvtkIOXML-6.1 -lvtkImagingCore-6.1 -lvtkIOImage-6.1 -lvtkImagingMath-6.1 -lz -L/g/g92/miguel/petsc-3.6.2/miguel-opt/lib -lpetsc -Wl,-rpath,/g/g92/miguel/petsc-3.6.2/miguel-opt/lib -lcmumps -ldmumps -lsmumps -lzmumps -lmumps_common -lpord -lscalapack -lHYPRE -L/usr/local/tools/openmpi-intel-1.8.4/lib -L/usr/local/tools/ic-14.0.174/composer_xe_2013_sp1.3.174/compiler/lib/intel64 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.7 -lml -llapack -lblas -lparmetis -lmetis -lX11 -lhwloc -lssl -lcrypto -lmpi_usempif08 -lmpi_usempi_ignore_tkr -lmpi_mpifh -lifport -lifcore -lm -lmpi -Wl,-rpath,/usr/local/tools/ic-14.0.174/lib -limf -lsvml -lirng -lipgo -ldecimal -lcilkrts -lstdc++ -lgcc_s -lirc -lpthread -lirc_s -Wl,-rpath,/usr/local/tools/openmpi-intel-1.8.4/lib -Wl,-rpath,/usr/local/tools/ic-14.0.174/composer_xe_2013_sp1.3.174/compiler/lib/intel64 -Wl,-rpath,/usr/lib/gcc/x86_64-redhat-linux/4.4.7 -ldl -Wl,-rpath,/g/g92/miguel/code/libmesh_2D/lib -L/g/g92/miguel/code/libmesh_2D/lib -lmesh_opt"

Agora eu gostaria de extrair os diretórios que começam com -L. Eu tentei fazer isso:

printenv LIBS | grep -o '\b-L\w*'

mas eu não obtenho nenhum resultado, enquanto faço isso (só para tentar entender o que está acontecendo)

printenv LIBS | grep -o '\b-l\w*'

extrai apenas as palavras "-linux" na minha variável. Eu gostaria de obter como resultado uma nova variável que fosse assim:

/ usr / lib / lib / usr / lib64-lglpk /usr/local/tools/vtk-6.1.0/lib ...

Eu obviamente não entendo muito sobre expressões regulares e muitas vezes me sinto confuso com as diferentes ferramentas usadas (grep, sed, awk, etc) e com as respostas que mostram um regexp encriptado sem qualquer explicação. Eu poderia ter uma referência útil por favor? A sintaxe de regexp é universal em todas as ferramentas mencionadas acima? Obrigado.

    
por balborian 30.03.2016 / 18:40

2 respostas

0

Vamos dar uma olhada na definição de limite de palavras:

There are three different positions that qualify as word boundaries:

  • Before the first character in the string, if the first character is a word character.
  • After the last character in the string, if the last character is a word character.
  • Between two characters in the string, where one is a word character and the other is not a word character.

Nenhum limite de palavra pode corresponder entre um caractere sem palavra e um traço, porque um traço também não é um caractere de palavra.

Também desde, por exemplo, slashes também não são caracteres de palavras e porque você não tem espaços nos caminhos , em vez de corresponder a \w* , seria mais sensível corresponder a [^ ]* . No entanto , uma vez que você também deseja excluir parte da correspondência, grep não é a ferramenta certa para o trabalho, a menos que você esteja usando uma versão grep que suporta PCREs:

printenv LIBS | grep -Po '(^| )-L[^ ]*'
% printenv LIBS | grep -Po '(^| )-L\K/[^ ]*'
/usr/lib
/lib
/usr/lib64
/usr/local/tools/vtk-6.1.0/lib
/g/g92/miguel/petsc-3.6.2/miguel-opt/lib
/usr/local/tools/openmpi-intel-1.8.4/lib
/usr/local/tools/ic-14.0.174/composer_xe_2013_sp1.3.174/compiler/lib/intel64
/usr/lib/gcc/x86_64-redhat-linux/4.4.7
/g/g92/miguel/code/libmesh_2D/lib

No entanto, isso depende dos caminhos que não contêm espaços e confiar nos caminhos que não contêm traços seria igualmente errado.

Geralmente, não há maneira segura de analisar essa string.

Minha sugestão é armazenar os caminhos em um array manualmente.

Pensando duas vezes, eu acho que espaços potenciais em um caminho seriam escapados para que o caminho seja interpretado corretamente?

Se for esse o caso, isso seria seguro:

printenv LIBS | grep -Po '(^| )-L\K\/.*?(?=([^\] |$))'
% export LIBS='-L/path\ with\ spaces -L/another\ path\ with\ spaces'
% printenv LIBS | grep -Po '(^| )-L\K\/.*?(?=([^\] |$))'
/path\ with\ space
/another\ path\ with\ spaces
    
por 30.03.2016 / 19:42
0
 echo $LIBS | awk '{for(i=1;i<=NF;i++){ if($i ~ /^-L/){print $i} } }'

o grep trabalha com linhas, como o sed faz. O awk trabalha com campos. para tal tarefa, eu prefiro usar o awk, no entanto o grep ou o sed também podem fazer o trabalho.

    
por 30.03.2016 / 19:34