2

I declared a long variable containing the libraries to use during the compilation:

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"

Now I would like to extract the directories that start with -L. I tried doing this:

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

but I do not obtain any result, whereas doing this (just for trying to understand what is going on)

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

extracts only the words "-linux" in my variable. I would like to obtain as a result a new variable that were like this:

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

I obviously do not understand much about regular expressions and I often feel confused with the different tools used (grep, sed, awk, etc) and the answers that show an encryptic regexp with no explanation whatsoever. Could I have a useful reference please? Is the regexp syntax universal across the above mentioned different tools? Thanks.

0

Let's take a look at the definition of word boundary:

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.

No word boundary can match in between a non-word character and a dash, because a dash is not a word character either.

Also since e.g. slashes are non-word characters as well, and since you don't have spaces in the paths, rather than matching \w* it would me more sensitive to match [^ ]*. However, since you also want to exclude part of the match, grep is not the right tool for the job, unless you're using a grep version which supports 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

However this relies on the paths not containing spaces, and relying on the paths not containing dashes would be just as wrong.

Generally, there's no safe way to parse that string.

My suggestion is to store the paths into an array manually.

On a second thought, I guess potential spaces in a path would be escaped in order for the path to be interpreted correctly?

If that's the case, this would be safe:

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
0
 echo $LIBS | awk '{for(i=1;i<=NF;i++){ if($i ~ /^-L/){print $i} } }'

grep works with lines, as sed does. awk works with fields. for such task, I'd prefer to use awk, however grep or sed could do the job as well.

  • Thanks, but how would you remove the -L from the output? – balborian Mar 30 '16 at 18:17
  • |sed -e 's/^-L//' – Mikhail Krutov Mar 30 '16 at 18:19
  • The pitfall being a path with a space, which would be printed only partially. Or printed only partially and followed by a nonsense in case of a path such as /usr/lib/my\ -Library/. I suggest you make this clear in the answer. – kos Mar 30 '16 at 18:27

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.