약 25000줄의 파일이 있습니다. 내 예제 입력과 원하는 출력을 살펴보십시오.
입력하다:
zone name tommy
* pwwn xxxxxxxx
pwwn xyzabcda
* pwwn xcvuytnm
zone name sammy
* pwwn akslapsl
* pwwn dfgsjasl
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
pwwn xyzabcda
원하는 출력:
zone name tommy
* pwwn xxxxxxxx
pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
pwwn xyzabcda
pwwn 앞의 각 줄에 *가 포함된 모든 영역을 제외하도록 출력하고 싶습니다. 내 예에서 영역 이름 sammy에는 pwwn 줄 세 개 모두에 *가 있으므로 영역 이름 sammy 아래의 모든 * 행을 제외했습니다.
Solaris 5.10, Korn Shell을 사용하십시오.
답변1
Awk
해결책:
awk '/^zone /{
if (f) print r;
r = $0; f = 0; next
}
{ r = r ORS $0; if (/^[^*]* pwwn/) f = 1; }
END{ if (f) print r }' file
산출:
zone name tommy
* pwwn xxxxxxxx
pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
pwwn xyzabcda
답변2
빠른 Perl 파이프라인으로 구현한 방법은 다음과 같습니다.
perl -p00e 's/\nzone/\n\nzone/g' inputfile \
| perl -n00e '$t = $_; s/^\*.*?\n//mg; print $t if /pwwn/' \
| perl -p00e 's/\n\n/\n/'
첫 번째 줄은 각 레코드 사이에 빈 줄을 추가합니다. 두 번째 라인은 각 레코드를 반복하면서 pwwn
레코드에서 *로 시작하는 라인을 모두 삭제한 후 남은 라인이 있는지 확인하고, 있으면 레코드를 인쇄한다. 세 번째 줄은 각 레코드를 구분하는 빈 줄을 제거합니다.
답변3
$ awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input
zone name tommy
* pwwn xxxxxxxx
pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
pwwn xyzabcda
스크립트 awk
는 레코드 구분 기호( RS
)를 입력 파일의 시작 부분이나 개행 문자로 설정하고 그 뒤에 "zone"이라는 단어가 옵니다. 그런 다음 적어도 하나의 개행 문자를 포함하고 그 뒤에는 아무것도 포함하지 않는 모든 "레코드"를 인쇄합니다 *
.
$0
"zone "은 모든 입력 레코드에서 자동으로 제거되므로 " zone"이라는 단어를 인쇄해야 합니다 awk
.RS
참고: RS
이는 단지 개행 자체가 아니기 때문에 $0
각 입력 줄 끝에 개행도 포함되어 있습니다(위에서 언급한 "zone"을 인쇄해야 하는 이유와 밀접하게 연관되어 있습니다). 이는 출력 끝에 추가 빈 줄이 있음을 의미합니다. 이것이 문제인 경우 이를 해결하는 가장 쉬운 방법은 sed
예를 들어 .
awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input | sed '$d'
마지막으로 pwwn
스크립트의 정규식 일치를 에서 일치 조건의 중요한 부분 /\n[^*]/
인 경우 로 변경합니다 /\n[^*] pwwn/
. (샘플 입력 시 출력은 동일하지만 더 큰 실제 입력과 다를 수 있음)