파일이 있고 파일에서 여러 파일 이름을 찾고 있습니다. 검색 텍스트 예시 intl_reg.jcl
. 일단 찾으면 그 위에 3줄의 텍스트를 가져와야 합니다. 예를 들어, 다음은 파일의 4줄입니다. "잔고 등록된 유학생"이라는 설명 앞의 텍스트는 항상 CHOICE이고 그 뒤에 설명이 옵니다.
CHOICE List registered international students with balances
SHORTCUT 8
PROCESS CHDIR /d3/locban/arsys
PROCESS CMD ksh /d3/locban/arsys/intl_reg.jcl
다음과 같이 나열하려면 grep 명령이 필요합니다.
intl_reg.jcl registered international students with balances
답변1
사용행복하다(이전 Perl_6)
~$ raku -e 'my @a; for lines() {
if @a.elems == 4 { @a.push($_); @a.shift }
elsif @a.elems < 4 { @a.push($_) };
if .match( /intl_reg\.jcl/ ) and @a.elems == 4 {
say $<>.Str, @a[0].split( /<?after List>/ ).[1] };
};' file
즉, @a
배열을 선언하고 lines
명령줄에서 읽어옵니다. 입력은 4가 될 때까지 배열 push
에 추가된 다음 최대 크기를 4 요소로 유지하기 위해 첫 번째 요소가 제거됩니다 .@a
elems
shift
배열에 4개의 요소가 포함된 것으로 match
확인 되면 일치하는 변수( 와 동일 )를 인쇄한 다음 3줄 전에 기록된 줄을 인쇄하여 원하는 문자열을 적절하게 반환합니다.and
$<>
$<>
$/
split
입력 예:
A CHOICE List registered international students with balances
A SHORTCUT 8
A PROCESS CHDIR /d3/locban/arsys
A PROCESS CMD ksh /d3/locban/arsys/intl_reg.jcl
B CHOICE List registered international students with balances
B SHORTCUT 8
B PROCESS CHDIR /d3/locban/arsys
B PROCESS CMD ksh /d3/locban/arsys/intl_reg.jcl
예제 출력:
intl_reg.jcl registered international students with balances
intl_reg.jcl registered international students with balances
답변2
다음 awk
프로그램이 작동합니다.
옵션 1: 듀얼 채널
awk -v d=3 -v s="intl_reg.jcl" '(NR==FNR) && index($0,s){i=FNR;nextfile}
FNR==(i-d){printf "%s\t%s\n",s,$0; exit}' input.txt input.txt
여기서는 입력 파일을 두 번 지정하여 두 번 처리하도록 합니다. 검색할 문자열이 awk
변수로 전달되고 s
, 거리가 awk
변수 로 전달됩니다 d
.
- 첫 번째 단계에서
NR
전역 줄 카운터는FNR
파일별 줄 카운터와 동일하며 각 줄에 문자열이 있는지 확인됩니다. 발견되면 행 번호가 변수에 저장되고i
실행이 즉시 다음 파일(=동일 파일의 다음 반복)로 점프합니다. - 두 번째 패스에서 프로그램은 현재 줄 번호가
d
이전에 인식된 패턴 발생 횟수( 에 저장되어 있음)보다 작은 지 확인합니다i
. 해당 줄이 발견되면 검색 문자열과 함께 인쇄되고 프로그램이 종료됩니다. 파일 부분의 나머지 부분을 유휴 상태로 순환하지 않도록 합니다.
옵션 2: 편도
프로세스 속도를 높이고 파일에 다시 액세스할 수 없는 경우(예: 파이프이기 때문에) 버퍼링이 포함된 단일 패스 솔루션을 사용할 수도 있습니다. 이 경우 특정 길이의 FIFO 버퍼가 필요합니다. 즉, d
너무 크면 실용적이지 않습니다(그러나 문제가 되는 경우는 거의 없음).d
awk -v d=3 -v s="intl_reg.jcl" 'FNR>1{for (j=d;j>0;j--) {buf[j]=buf[j-1]}; buf[0]=$0}
FNR>d && match($0,s) {printf "%s\t%s\n",s,buf[d];exit}' input.txt
buf
d+1
그러면 버퍼 내용이 각 새 줄에서 "위로 이동"하고 현재 줄은 항상 마지막 몇 줄로 버퍼를 채울 것 입니다 buf[0]
. 일단 검색 문자열이 발견되면 줄의 내용이 인쇄됩니다 buf[d]
. 이는 d
현재 줄 앞의 줄입니다. 이번에도 성능상의 이유로 프로그램이 즉시 종료됩니다.
답변3
match=intl_reg.jcl
tac {file} |
sed -n "/$match/ { n; n; n; s/^CHOICE/$match/p }"
정규식 연산자를 $match
포함 하거나 포함 하지 않도록 하세요 . /
(이것은 .
실제로 와일드카드이므로 이 규칙을 즉시 어기십시오. 이는 문제가 될 수도 있고 아닐 수도 있습니다.)
답변4
awk를 사용하십시오.
$ awk -v t='intl_reg.jcl' '{a[NR%4]=$0} index($0,t){$0=a[(NR-3)%4]; $1=$2=""; print t $0}' file
intl_reg.jcl registered international students with balances