
특정 데이터를 추출하고 재정렬하려는 파일이 있습니다. 이전 파일에는 원시 데이터가 포함되어 있습니다. 이 파일은 입력입니다.
참조:cve,2017-8962 시드:45885 참조:cve,2016-10033 참조:cve,2016-10034 참조:cve,2016-10045 참조:cve,2016-10074 시드:45917 참조:cve,2017-8046 시드:45976 참조:cve,2018-6577 참조:cve,2018-6578 시드:46062
아래 파일은 필요한 출력이 포함된 새 파일입니다.
참조:cve,2017-8962 시드:45885 참조:cve,2016-10033 시드:45917 참조:cve,2016-10034 시드:45917 참조:cve,2016-10045 시드:45917 참조:cve,2016-10074 시드:45917 참조:cve,2017-8046 시드:45976 참조:cve,2018-6577 시드:46062 참조:cve,2018-6578 시드:46062.
설명: 예제 sid:45917에는 4개의 참조가 있습니다(참조: cve,2016-10033 참조: cve,2016-10034 참조: cve,2016-10045 참조: cve,2016-10074). 각 참조를 분할해야 합니다. sid를 다른 것 아래에 추가합니다(참고: sid 뒤에는 항상 참조가 옵니다.), 이와 같이 반복적인 블록이 있으므로 참조가 여러 개인 경우 새 파일 순서로 추가해야 합니다.
답변1
사용하시는 것 같으니후불 sid:
s (multipe references:
뒤에 단일 sids:
=> references:
및 쌍이 옴 sid:
), 두 가지 솔루션.
해결 방법 1: 반전
다음 명령을 사용하면 됩니다 tac
(이것은고양이역순으로) 입력과 출력을 반대로 하려면:tac input | awk | tac > output
awk 부분의 경우 sid:
s를 복제하면 됩니다.
gawk '/^sid:/{sid=$0};/^reference:/{print sid "\n" $0}'
해결 방법 2: 배열
reference:
s가 오면 배열에 저장 한 다음 해당 항목을 만나면 다시 뱉어냅니다.sid:
gawk 'BEGIN{r=0};/^reference:/{ref[r++]=$0};/^sid:/{for(n=0;n<r;n++){print ref[n] "\n" $0};r=0}' /tmp/test.txt
/^reference:/{ref[r++]=$0}
: ref로 시작하는 각 라인에 대해... 라인을 배열에 저장하고 'r' 포인터를 다음 요소로 이동합니다.
/^sid:/{for(n=0;n<r;n++){print ref[n] "\n" $0};r=0}
: 줄이 sid로 시작될 때마다 r 포인터(for...)까지 전체 배열을 탐색하고 각 요소에 대해 저장된 참조와 현재 줄(=sid)을 인쇄한 다음 r을 다시 처음으로 재설정하여 시작합니다. 다음 참조로 다시 한번.
답변2
awk 'BEGIN { i=0; }
/^reference:/ { ref[i++] = $0; }
/^sid:/ { for(j=0; j<i; j++) { print ref[j]; print; } i=0; }' inputfile > outputfile
설명:
BEGIN { i=0; }
0
빈 문자열이 아닌 숫자 값으로 해석되도록 변수를 초기화합니다""
./^reference:/ { ref[i++] = $0; }
reference:
(^
는 줄의 시작 부분에 대한 앵커) 로 시작하는 모든 줄에 대해 전체 줄을$0
배열 요소에 복사ref[i]
하고 인덱스를 증가시킵니다.i++
/^sid:/ { ... }
sid:
... 로 시작하는 모든 줄에 대해for(j=0; j<i; j++) { ... }
마지막으로 사용된 배열 요소 이후의 배열 요소를 가리키 므로i
index 를 사용하여 작성된 모든 배열 요소를 반복합니다j
.print ref[j];
배열 요소의 내용, 즉 저장된reference:
줄을 인쇄합니다.print;
현재 줄, 즉sid:
줄을 인쇄합니다.i=0;
reference:
다음 행 그룹의 시작 부분으로 배열 인덱스를 재설정합니다.
스크립트는 다음 가정을 기반으로 합니다.
- 입력은 일련의 블록으로 구성되며 모든 블록에는 다음이 포함됩니다.
reference:
하나 이상의 줄로 이루어진 시퀀스- 한
sid:
줄
- 마지막 줄은 한
sid:
줄이어야 합니다. - 일치하지 않는 줄은 무시됩니다.
원래 질문에서 나는 변환의 잘못된 방향을 가정했습니다. 두 번째 스크립트는 반대 방향으로 변환합니다.
awk 'BEGIN { oldsid=""; ref=""; }
/^reference:/ { ref=$0; }
/^sid:/ { if(oldsid != $0) { if(oldsid != "") print oldsid; } if(ref!="")print ref; oldsid=$0; }
END { if (oldsid != "") print oldsid; }' inputfile > outputfile
설명:
BEGIN { oldsid=""; ref=""; }
명확성을 위해 변수를 초기화합니다. 실제로는 필요하지 않습니다./^reference:/ { ref=$0; }
reference:
save the line$0
to Variable 로 시작하는 모든 줄에 대해ref
아직 인쇄하지 마세요./^sid:/ { ... }
sid:
... 으로 시작하는 모든 줄에 대해if(oldsid != $0) { if(oldsid != "") print oldsid; }
sid:
지금 줄이 변경된 경우reference:
저장된 마지막 줄은ref
새 줄에 속하므로sid:
아직 인쇄하지 않습니다. 비어 있지 않으면 동일한 줄oldsid
의 이전 블록이 완료되었으므로 이제 인쇄할 수 있습니다. 첫 번째 를 찾으면 비어 있을 것입니다 .reference:
sid:
oldsid
sid:
if(ref!="")print ref;
저장된 가 있으면reference:
지금 인쇄하세요. (해당 라인으로 이전 블록을 닫았거나sid:
현재가 이전 블록과reference:
동일하다는 것을 이제 알고 있습니다.) 모든 라인 앞에 라인이 있다고sid:
가정하므로 빈 문자열을 확인하는 것은 실제로 필요하지 않습니다 .sid:
reference:
oldsid=$0;
sid:
다음 행을 얻을 때 비교를 위해 현재 행을 저장하십시오 . 현재 줄은 아직 인쇄되지 않았습니다.END { if (oldsid != "") print oldsid; }
마지막에 마지막으로 저장된sid:
줄이 있으면 인쇄합니다. (입력 파일이 비어 있으면 여기에 빈 줄이 인쇄되지 않습니다.)
이 스크립트는 다음 가정을 기반으로 합니다.
- 모든
reference:
뒤에는sid:
- 같은 줄의 모든 쌍이
reference:
서로 이어집니다.sid:
sid: