같은 행에 있는 두 검색 패턴 사이의 값을 추출합니다.

같은 행에 있는 두 검색 패턴 사이의 값을 추출합니다.

Output.dat 파일에 다음 내용이 있습니다. dn: uid=와 사이의 값을 추출해야 합니다 .,ou=

 dn: uid=user1,ou=Active,ou=Member,dc=domain,dc=org
 dn: [email protected],ou=Active,ou=Member,dc=domain,dc=org
 dn: uid=usertest,ou=Active,ou=Member,dc=domain,dc=org
 dn: uid=abc1,ou=Active,ou=Member,dc=domain,dc=org
  • 나는 사용하려고
    sed -e '/dn: uid=/,/,ou=/p' output.dat but
    
    값 대신 전체 행을 반환합니다.
  • 사용하려고 할 때
    sed -e '/dn: uid=/,/,ou=/\1/p' output.dat
    
    그런 다음 다음 오류가 발생합니다.
    sed: -e expression #1, char 18: unknown command: `\'
    

답변1

PCRE ( ) 를 지원하는 GNU grep 버전이 있는 경우 -P다음을 의미한다고 가정합니다.첫 번째일어난,ou

grep -oP '(?<=dn: uid=).+?(?=,ou=)' file

어울리고 싶다면두번째 ,ounon-greedy ?수정자를 제거할 수 있습니다.

grep -oP '(?<=dn: uid=).+(?=,ou=)' file

괄호 안의 표현식은 길이가 0인 어설션(일명주위를 둘러보세요)는 일치 항목의 일부를 구성하지만 결과의 일부로 반환되지 않음을 의미합니다. Perl에서도 기본적으로 동일한 작업을 수행할 수 있습니다.

perl -ne 'print "$1\n" if /(?<=dn: uid=)(.+?)(?=,ou=)/' file 

뭔가 할 수 있어요비슷한sed에서는 일반(0이 아닌 길이) 그룹화를 사용합니다. 예를 들어 GNU sed의 경우 다른 변형에는 추가 이스케이프가 필요할 수 있습니다.

sed -rn 's/(.*dn: uid=)([^,]+)(,ou=.*)/\2/p' file

또는 약간 단순화됨

sed -rn 's/.*dn: uid=([^,]+),ou=.*/\1/p' file

sed에는 탐욕스럽지 않은 일치 옵션이 없기 때문에 [^,]이것은 약간의 해킹입니다.


나중에 생각: 이것이 정확히 요청한 작업을 수행하지는 않지만 실제로 원하는 작업은 name=value파일에서 쉼표로 구분된 쌍을 읽은 다음 첫 번째 필드의 값을 이름에서 추가로 분리하는 것 같습니다. 다음을 포함하여 다양한 방법으로 이를 달성할 수 있습니다.

awk -F, '{sub(".*=","",$1); print $1}' file

또는 다음과 같은 순수한 bash 솔루션

while IFS=, read -r a b c d; do printf '%s\n' "${a#*=}"; done < file 

답변2

이것은 awk에게 좋은 일입니다. 정규식을 사용하는 대신 문자열을 분할할 수 있습니다. 해결책은 다음과 같습니다.

$ awk -F= '{ split($2,arr,","); print arr[1]  }' test.txt
user1
[email protected]
usertest
abc1

답변3

그리고 sed:

sed 's/[^=]*=\([^,]\+\),.*/\1/' file

이는 uid=해당 줄에 첫 번째 발생이 있을 것이라고 가정하고 해당 줄의 첫 번째 인스턴스에서 중지 =하기를 원한다고 가정합니다 .,ou=

설명하다

=이렇게 하면 문자가 아닌 문자( [^=]*) 뒤에 =일치하는 문자를 원하는 만큼 찾고 , 쉼표가 아닌 문자( \([^,]\+\)) 뒤에 쉼표와 줄의 나머지 부분( ,.*)을 최대한 많이 저장합니다. 즉, 첫 번째 쉼표 앞과 뒤의 모든 내용을 해당 줄의 =첫 번째 쉼표 뒤에 있는 쉼표가 아닌 문자로 바꿉니다 .=

답변4

길이순으로 몇 가지 추가 옵션:

  1. grepPCRE를 사용한 GNU

    grep -oP 'uid=\K[^,]+' file 
    

    \K스위치와 결합하면 인쇄 -o된 후 grep가장 긴 문자가 아닌 결과만 생성됩니다.,uid=

  2. awk

    awk -F'[=,]' '{print $2}' file 
    

    -F'[=,]필드 구분 기호를 다음으로 설정하거나 =두 번째 ,필드는 사용자 이름입니다.

  3. sed

    sed -r 's/.{8}([^,]*).*/\1/' file 
    

    이는 처음 7개 문자( .{7}) 와 일치하고 =가장 긴 비 ,as 부분을 캡처 \1하고 전체 줄을 로 바꿉니다 \1.

  4. perl

    perl -pe 's/.+?=([^,]+).*/$1/' file 
    

    -pe"-e로 지정된 스크립트를 적용한 후 각 줄을 인쇄합니다"를 의미합니다 . 은 대체 연산자 이고 s///, 정규식은 첫 번째( .+?, ?가능한 가장 짧은 문자열과 일치하도록)를 찾은 다음 그 다음 =으로 가장 긴 비문자 세그먼트를 캡처합니다. 캡처된 콘텐츠(괄호 안의 콘텐츠)와 일치하는 콘텐츠를 ,바꿉니다 .s///

  5. cut

    cut -d'=' -f 2 file | cut -d ',' -f 1 
    

    -d구분 기호를 로 설정 =하면 두 번째 ( -f 2) 필드는 가 됩니다 username,ou. 두 번째는 구분 기호 cut역할을 하며 사용자 이름을 별도로 인쇄합니다.,

관련 정보