다음과 같은 파일이 있습니다.
pin(ABC) {
a b c d e f {
abc
}
}
pin(XYZ) {
g h i j k {
j k {
cg {
}
}
}
}
abcd pqrs rstu
mango banana tree
pin(PQR) {
mango
}
이제 다음과 같이 텍스트를 grep하고 싶습니다. -
ABC를 입력으로 사용하면 출력은 아래와 같이 "pin(ABC) {"에서 시작하여 일치하는 대괄호 "}"까지 내용이 포함된 ABC라는 파일이어야 합니다.
pin(ABC) {
a b c d e f {
abc
}
}
PQR을 제공하면 출력은 다음 내용을 포함하는 PQR이라는 파일이어야 합니다.
pin(PQR) {
mango
}
잠깐만요, pin() 내부의 단어에 대해
한 가지 방법은 "pin(ABC"에서 다음 이름 "pin"으로 텍스트를 grep하고 출력을 "ABC"라는 파일로 보내는 것입니다. ABC가 다음인 경우에만 작동하지만 PQR 및 XYZ 사례에서 실패했습니다.
답변1
$ pcregrep -Mo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
pin(ABC) {
a b c d e f {
abc
}
}
pcregrep
GNU는 없지만 PCRE grep
모드를 지원하도록 빌드되었으며 파일이 너무 크지 않고 NUL 문자를 포함하지 않는 경우 다음을 수행할 수 있습니다.
grep -zPo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
이들 ( pcregrep
및 grep -P
)은 재귀 정규식 연산자를 지원하는 PCRE 모드를 사용합니다.
pcregrep -M
여러 줄 모드를 켜고( pcregrep
정규식을 일치시킬 때 필요에 따라 여러 줄을 가져올 수 있음) grep -z
대신 레코드를 NUL로 구분하도록 지시합니다.철사.
위의 트릭은 (?1)
연산자에 있습니다. 즉,내부 정규식첫 번째팔렌 그룹따라서 우리는 재귀적인 정규식을 가지고 있습니다: 우리는 0개 이상의 ( ) 중괄호가 아닌 문자 ( , 소유격 버전입니다 ) {
의 시퀀스가 뒤따르는 시퀀스와 일치합니다.*
[^{}]++
++
+
또는다시 외부 정규식 (...)
( {
뒤에...)을 사용합니다.
pcrepattern
자세한 내용은 매뉴얼 페이지를 참조하십시오. 이것은 거기에 있는 예제에서 거의 그대로 복사되었습니다.
사용 perl
:
perl -l -0777 -ne 'print $& while /pin\(ABC\) (\{([^{}]++|(?1))*\})/g'
( grep
메모리의 전체 파일을 먹는 것과 같습니다).