Linux - 파일 라인에서 특정 패턴의 모든 발생을 찾습니다.

Linux - 파일 라인에서 특정 패턴의 모든 발생을 찾습니다.

Linux에 다음과 같은 줄이 포함된 파일이 있습니다.

(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)

내 목표는 해당 행에 있는 그룹 목록을 채우는 것입니다. 예를 들면 다음과 같습니다.

Group1

Group2

Group3

Group4

답변1

with pcregrep( Perl C호환 R정규 E표현식 grep):

pcregrep -io1 '\(memberOf=CN=(.*?)\)'

또는 직접 사용하십시오 perl.

perl -lne 'print $1 while /\(memberOf=CN=(.*?)\)/gi'

( 여기서 LDAP 속성 이름으로 사용된 -i또는 플래그는 대소문자를 구분하지 않습니다.)i

grep구현에서 해당 옵션을 지원하는 경우 -P( grepPCRE 지원으로 빌드할 때 GNU가 지원하는 것처럼) 비표준 옵션도 지원할 가능성이 높으며 -o다음을 수행할 수 있습니다.

grep -iPo '\(memberOf=CN=\K.*?(?=\))'

다른 구현에서는 출력 캡처 그룹을 지원하지 않으므로 여기서 \K및 의 미리보기 연산자는 및 가 (memberOf=CN=출력 )에 포함되지 않음 을 나타내기 위해 사용됩니다 .greppcregrep

POSIX 유틸리티를 사용하면 거의 동일한 작업을 수행할 수 있습니다.

sed -n '
  /([mM][eE][mM][bB][eE][rR][Oo][fF]=[Cc][Nn]=\([^)]*\))\(.*\)/ {
    s//\
\1\
\2/
    s/.*\n\(.*\n\)/\1/
    P;D
  }'

문자열이 셸 스칼라 변수에 저장되어 있고 결과 그룹을 셸 배열 변수에 저장하려는 경우 셸을 사용하여 zsh다음을 수행할 수 있습니다.

set -o extendedglob

string='(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)'
groups=()

: ${string//(#ib)[(]memberOf=CN=([^)]#)[)]/${groups[$#groups+1]=$match[1]}}

아니면 GNU에서 얻으세요 grep:

groups=(
  ${(0)"$(
    print -rN -- $string |
      grep -ziPo '\(memberOf=CN=\K.*?(?=\))'
  )"}
)

Bash 4.4+와 동일:

readarray -td '' groups < <(
  printf '%s\0' "$string" |
    grep -ziPo '\(memberOf=CN=\K.*?(?=\))'
) && wait "$!"

답변2

Raku(이전 Perl_6) 사용

raku -ne 'put $/.join("\n") if m:g/\(memberOf\=CN\= <(.*?)> \)/;'

또는

raku -ne 'put $/.join("\n") if m:g/<?after \(memberOf\=CN\= > (.*?) <?before \) > /;'

간단히 말해서, 예 1은 <(…)>Raku에서 일치 구분 기호를 사용하여 정규식 엔진에 를 삭제하도록 지시합니다 <(.*?)>. 예 2는 <?after "pattern1" >긍정적인 예측과 <?before "pattern2" >긍정적인 예측을 사용하여 그 사이의 모든 것을 격리합니다. 대소문자를 구분하지 않는 것이 중요하다면 m:g('match-global')을 m:g:i('match-global case-insensitive') 로 변경하세요.

입력 예:

(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)

출력 예(1):

Group1
Group2
Group3
Group4

또는 출력 예(2):

Group1 Group2 Group3 Group4

OP에 예제 줄과 유사한 여러 줄이 포함된 파일이 있다고 가정하면 모든 출력을 한 줄로 반환하는 것이 합리적일 수 있습니다. 위의 예 중 하나에 대해 각 줄별 캡처가 한 줄씩 반환되도록 간단히 변경합니다(위의 출력 2) $/.join("\n").$/

마지막으로 OP는 "그룹" 목록의 위치 정보를 인코딩할 수 있습니다(예: 왼쪽의 하위 그룹 #, 오른쪽의 상위 그룹 #). 이 경우 일치 항목을 삭제하고 다음과 같이 comb()표시하는 것이 더 합리적일 수 있습니다 ..pairs

raku -ne '.raku.say for .comb(/<?after \(memberOf\=CN\= > (.*?) <?before \) > /).pairs;' 

0 => "Group1"
1 => "Group2"
2 => "Group3"
3 => "Group4"

https://docs.raku.org/언어/regexes
https://raku.org

답변3

이 솔루션은 와 다소 유사 @bxm하지만 sedpure 대신 한 단계를 사용합니다 grep.

grep -Eo '\(memberOf=CN=[^()]*\)' |
sed 's/(memberOf=CN=\(.*\))/\1/' 

입력하다:

(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)
(memberOf=CN=GroupA1)
(memberOf=CN=GroupA2)(memberOf=CN=GroupA3)
(memberOf=CN=GroupA4)
(rememberOf=CN=GroupX1)(memberOf=CN=GroupX2)
(numberOf=CN=GroupX4)
(memberOf=CN=GroupB1)(memberOf=CN=GroupB2)(memberOf=CN=GroupB3)(memberOf=CN=GroupB4)

산출:

Group1
Group2
Group3
Group4
GroupA1
GroupA2
GroupA3
GroupA4
GroupX2
GroupB1
GroupB2
GroupB3
GroupB4

의 출력은 다음의 입력 grep에 표시됩니다 .sed

(memberOf=CN=Group1)
(memberOf=CN=Group2)
(memberOf=CN=Group3)
(memberOf=CN=Group4)
...

sed그런 다음 해당 출력을 가져와 선행 (memberOf=CN=및 후행을 제거합니다 ).

이 코드는 다음 줄에 더 많은 내용을 와일드카드로 추가하여 좀 더 일반화할 수 있습니다 sed.

grep -Eo '\(memberOf=CN=[^()]*\)' |
sed 's/.*=\(.*\))/\1/'

답변4

이 문제를 해결하는 방법은 여러 가지가 있습니다. 여기에서는 널리 사용 가능한 기능을 사용하고 grep읽기 쉽게 만드는 데 중점을 둔 솔루션이 있습니다.

입력이 어떻게 거기에 도달하는지 말하지 않았으므로 파이프라고 가정합니다. 파일 입력에 적응하는 것은 간단합니다.

echo "(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)" \
  | grep -Eo "[(]memberOf=CN=[^)]+" \
  | grep -Eo "[^=]+$"

이는 두 단계로 수행됩니다.

(memberOf=CN=something첫째, 끝나지 않고 모든 패턴을 추출합니다 ). 이는 두 번째 단계에서 중요합니다. 이는 "무료"이므로 두 번째 단계의 작업이 더 쉬워집니다. 이 패턴에 맞지 않는 입력 문자열은 무시되므로 필요한 문자열이 다른 곳에 묻혀 있는 상황에서도 작동해야 합니다.

=다음으로 줄 끝부터 시작하여 거꾸로 작업하면서 가 아닌 모든 항목을 일치시킵니다 . 이는 memberOf=CN=문자열의 일부를 제거하는 효과가 있습니다.

입력의 대소문자를 보장할 수 없는 경우 i첫 번째 플래그에 추가합니다 grep.

주의할 점: 이스케이프가 있거나 값 에 있는 )경우 예상대로 작동하지 않습니다.=CN

관련 정보