두 가지 유형의 패턴이 포함된 거대한 파일이 있습니다.모드 1그리고모드 2, 모드 1이전에도 여러 번 이런 일이 있었을 수도 있습니다.모드 2나타나다. 나는 각각의 마지막 발생을 파악하고 싶습니다.모드 1각각 전에모드 2.
입력 파일:
some text
pattern1=1
some lines
pattern1=2
some lines
pattern1=3
some lines
pattern2
some lines
pattern1=4
some lines
pattern1=5
some lines
pattern1=6
some lines
pattern1=7
some lines
pattern2
원하는 출력:
pattern1=3
pattern1=7
grep
내가 시도한 사이의 줄 수를 알 때모드 2그리고 이전 것모드 1:
grep -B400 "pattern2" | grep "pattern1"
하지만 두 패턴 사이의 줄 수에 관계없이 모든 파일에서 실행할 수 있는 고유한 명령이 필요합니다.
답변1
$ awk '/pattern1/{x=$0} /pattern2/{print x}' input
pattern1=3
pattern1=7
일치 항목(전체 줄)을 pattern1
변수에 저장 x
하고 pattern2
일치 항목이 발생하면 인쇄합니다. 앞에 빈 줄이 있으면 pattern2
빈 줄이 인쇄되며 pattern1
, 이것이 바람직하지 않은지 여부를 감지하려면 더 많은 논리가 필요합니다. 입력의 끝이 앞에 오지 pattern1
않는 모든 후행 a는 제거됩니다.pattern2
답변2
@thrig의 답변은 훌륭하지만 몇 가지 추가 테스트 사례를 처리하기 위해 몇 가지 수정을 했습니다. 다음 스크립트:
pattern2
처음 발생하기 전에 발생하면 빈 줄이 인쇄되지 않습니다pattern1
.pattern2
after가 여러 번 발생하면 중복된 줄이 인쇄되지 않습니다pattern1
.
수정된 입력 파일:
pattern2
some text
pattern1=1
some lines
pattern1=2
some lines
pattern1=3
some lines
pattern2
pattern2
some lines
pattern1=4
some lines
pattern1=5
pattern2
some lines
pattern1=6
some lines
pattern1=7
some lines
pattern2
다음 스크립트는 귀하의 기사에서 설명하는 작업을 수행하는 것으로 나타납니다.
$ awk '/pattern1/{x=$0} length(x) && /pattern2/{print x;x=""}' file
pattern1=3
pattern1=5
pattern1=7
답변3
세 가지 grep
호출:
원본 입력 파일과
^pattern1=
일치하는 행만 추출합니다.^pattern2$
grep -e '^pattern1=' -e '^pattern2$' file
일치하는 행
^pattern2$
과 바로 앞의 행을 가져옵니다(비표준-B
옵션 사용).grep -B1 '^pattern2$'
일치하는 모든 행을 가져옵니다
^pattern1=
.grep '^pattern1='
모든 것을 한 번에:
grep -e '^pattern1=' -e '^pattern2$' file |
grep -B1 '^pattern2$' |
grep '^pattern1='
이는 다음과 동일한 엣지 케이스를 처리합니다.user000001의 답변, 즉 pattern2
사이에 줄이 없는 줄이 많으면 pattern1
중복된 줄을 출력하지 않으며 , pattern2
파일 시작 부분에 있는 줄에 대해 빈 줄을 생성하지 않습니다.
사용 sed
:
sed -e '/^pattern1=/ { h; d; }' \
-e '/^pattern2$/ x' \
-e '/^pattern1=/ !d' file
현재 행이
pattern1
행인 경우 예약된 공간에 저장하고 폐기합니다.현재 행이
pattern2
행인 경우 예약된 공간을 바꿉니다.현재 행이 현재 행이 아니면
pattern1
삭제됩니다.(암시적) 현재 줄을 인쇄합니다. 이전 명령을 사용하면 현재 줄은
pattern1
검색 줄로 인해pattern2
예약된 공간에서 교체된 줄이어야 합니다. 따라서 공간을 예약하면 반드시 행이 예약되므로pattern2
해당pattern1
행이 여러 번 출력되지 않습니다.
답변4
egrep "^pattern1|^pattern2" <file> | grep -B 1 "^pattern2" | grep "^pattern1"
첫 번째 egrep은 두 패턴 중 하나를 포함하는 줄만 가져옵니다(출력에서 알 수 없는 다른 줄은 모두 제거). 두 번째 grep은 Pattern2와 그 앞의 모든 행을 가져옵니다. 이는 앞에 패턴 1이 없는 패턴 2가 있는 행을 삭제하는 데 사용됩니다. 세 번째 grep은 나머지 Pattern1 행만 반환합니다.