다음 내용이 포함된 파일이 있습니다.
dn : Does not matter
uid=321 456 678
foo=/234
bar=/456
git=/543
uid=321 456 678
uid=678 987 098
foo=/234
bar=/456
git=/543
dn : Does it matter
uid=321 456 678
foo=/543
bar=/423
git=/501
uid=
예상되는 출력이 다음과 같도록 연속된 항목과 그 뒤의 3줄을 제거하고 싶습니다 .
dn : Does not matter
uid=321 456 678
foo=/234
bar=/456
git=/543
dn : Does it matter
uid=321 456 678
foo=/543
bar=/423
git=/501
두 개의 서버에서 이것을 시도했습니다. 안타깝게도 제가 가장 많이 사용해 본 서버에는 액세스할 수 없습니다. 그래서 두 번째 서버에서는 다음과 같은 다양한 변형을 시도했지만 원하는 결과를 얻을 수 없었습니다.
sed '/^ uid=/N;{/\n uid= & & \n ^change type & & \n ^replace/d;}' pattern2.txt
awk '{/pat/?f++:f=0} f==2 {f--;}; 1' < pattern2.txt
sed '/^ uid=/N;{/\n uid=/D;}' pattern1.txt
awk '{/ uid=/?f++:f=0} f==2' pattern1.txt
답변1
사용 sed
:
$ sed -f script.sed file
dn : Does not matter
uid=321 456 678
foo=/234
bar=/456
git=/543
dn : Does it matter
uid=321 456 678
foo=/543
bar=/423
git=/501
... script.sed
어디
H # Append a newline and the current line to the hold space
/^$/bout # Empty line: branch to ':out'
$bout # Last line: branch to ':out'
d # Delete line, start again from the top
:out
x # Swap in the data from the hold space
/uid.*uid/d # Delete the data if it contains two "uid"
s/\n// # Remove the first embedded newline
# (implicit print)
이는 sed
"예약된 공간"(일반 버퍼)에 읽은 줄을 수집하고, 빈 줄이나 입력 끝을 만나면 예약된 공간에는 원본 파일의 "청크" 중 하나가 포함됩니다. 이러한 블록에 문자열 인스턴스가 두 개 포함되어 있으면 uid
해당 블록은 삭제되고, 그렇지 않으면 출력됩니다.
답변2
나는 이것이 단순화될 수 있다고 생각 awk
하지만 아직은 그렇지 않다.
awk '/uid=/ && p~/uid=/{c=4; next}
!(c && c--) && NR>1{print p} {p=$0}
END{if(c==0)print p}' ip.txt
- 기본적으로 awk의 초기화되지 않은 변수는 상황에 따라 빈 문자열 또는 0이 됩니다.
/uid=/ && p~/uid=/
현재 줄과 이전 줄에 다음이 포함되어 있는 경우uid=
c=4; next
건너뛸 행 수c
(최종 논리로 인해 1 추가)로 초기화합니다. 또한 나머지 코드는 건너뛰세요.
!(c && c--) && NR>1{print p}
현재 줄 번호가 1보다 크면 이전 줄을 인쇄합니다c==0
.c
보다 크면 계속0
감소합니다.c==0
{p=$0}
나중에 사용할 수 있도록 이전 줄을 저장하세요.END{if(c==0)print p}
다음과 같은 경우 마지막 줄을 인쇄하세요.c==0