컴파일 중에 사용할 라이브러리가 포함된 긴 변수를 선언했습니다.
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*
일치하는 데 더 민감해집니다 [^ ]*
.하지만부분 일치도 제외하려고 하므로 PCRE를 지원하는 버전을 grep
사용하지 않는 한 작업에 적합한 도구가 아닙니다 .grep
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도 해당 작업을 수행합니다.