Linux에 다음과 같은 줄이 포함된 파일이 있습니다.
(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)
내 목표는 해당 행에 있는 그룹 목록을 채우는 것입니다. 예를 들면 다음과 같습니다.
Group1
Group2
Group3
Group4
답변1
with pcregrep
( P
erl C
호환 R
정규 E
표현식 grep
):
pcregrep -io1 '\(memberOf=CN=(.*?)\)'
또는 직접 사용하십시오 perl
.
perl -lne 'print $1 while /\(memberOf=CN=(.*?)\)/gi'
( 여기서 LDAP 속성 이름으로 사용된 -i
또는 플래그는 대소문자를 구분하지 않습니다.)i
grep
구현에서 해당 옵션을 지원하는 경우 -P
( grep
PCRE 지원으로 빌드할 때 GNU가 지원하는 것처럼) 비표준 옵션도 지원할 가능성이 높으며 -o
다음을 수행할 수 있습니다.
grep -iPo '\(memberOf=CN=\K.*?(?=\))'
다른 구현에서는 출력 캡처 그룹을 지원하지 않으므로 여기서 \K
및 의 미리보기 연산자는 및 가 (memberOf=CN=
출력 )
에 포함되지 않음 을 나타내기 위해 사용됩니다 .grep
pcregrep
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"
답변3
이 솔루션은 와 다소 유사 @bxm
하지만 sed
pure 대신 한 단계를 사용합니다 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