从长变量中提取库目录

从长变量中提取库目录

我声明了一个 long 变量,其中包含编译期间要使用的库:

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"

现在我想提取以-L 开头的目录。我尝试这样做:

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

但我没有得到任何结果,而这样做(只是为了试图了解发生了什么)

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

仅提取变量中的“-linux”一词。我想获得一个像这样的新变量:

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

显然,我对正则表达式不太了解,并且经常对使用的不同工具(grep、sed、awk 等)以及显示加密正则表达式且没有任何解释的答案感到困惑。请问可以给我一个有用的参考吗?正则表达式语法在上述不同工具中是否通用?谢谢。

答案1

我们看一下单词边界的定义:

三种不同的位置都可以作为单词边界:

  • 在字符串中的第一个字符之前,如果第一个字符是单词字符
  • 在字符串中的最后一个字符之后,如果最后一个字符是单词字符。
  • 字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符。

非单词字符和破折号之间没有单词边界可以匹配,因为破折号也不是单词字符。

另外,因为例如斜杠也是非单词字符,并且因为路径中没有空格,而不是匹配\w*它会让我对匹配更敏感[^ ]*然而,因为您还想排除部分匹配,所以grep不是适合该工作的工具,除非您使用grep支持 PCRE 的版本:

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

然而,这依赖于不包含空格的路径,并且依赖于不包含破折号的路径同样是错误的。

一般来说,没有安全的方法来解析该字符串。

我的建议是手动将路径存储到数组中。

再想一想,我想为了正确解释路径,路径中的潜在空间将被转义?

如果是这样的话,这将是安全的:

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

答案2

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

grep 与行一起工作,就像 sed 一样。 awk 与字段一起使用。对于这样的任务,我更喜欢使用 awk,但是 grep 或 sed 也可以完成这项工作。

相关内容