패턴 일치 후 이전 줄을 인쇄하기 위해 sed를 사용하시겠습니까?

패턴 일치 후 이전 줄을 인쇄하기 위해 sed를 사용하시겠습니까?

일치하는 항목이 발견될 때마다 이전 줄을 인쇄하고 싶습니다. 이해 grep -A하고 -B선택하겠습니다. 그러나 내 Solaris 5.10 시스템은 이러한 옵션을 지원하지 않습니다.

만 사용하고 싶습니다 sed.

Foo.txt:

Name is : sara
age is : 10
Name is : john
age is : 20
Name is : Ron
age is : 10
Name is : peggy
age is : 30

Out.txt:

Name is : sara
Name is : Ron

내가 일치시키려는 패턴은 age is : 10.

내 환경은 솔라리스 5.10.

답변1

$ sed -n '/age is : 10/{x;p;d;}; x' Foo.txt 
Name is : sara
Name is : Ron

위의 내용은 GNU sed에서 테스트되었습니다. Solaris의 sed가 세미콜론과 함께 연결 명령을 지원하지 않는 경우 다음을 시도하십시오.

$ sed -n -e '/age is : 10/{x;p;d;}' -e x Foo.txt 
Name is : sara
Name is : Ron

어떻게 작동하나요?

sed에는 보류 공간과 패턴 공간이 있습니다. 개행 문자는 패턴 공간으로 읽혀집니다. 스크립트의 아이디어는 이전 줄을 예약된 공간에 저장하는 것입니다.

  • /age is : 10/{x;p;d;}

    현재 줄에 가 포함되어 있으면 age is : 10다음을 실행합니다.

    x: 이전 라인이 패턴 공간에 있도록 패턴을 교환하고 공간을 예약합니다.

    p:이전 줄을 인쇄합니다.

    d: 패턴 공간을 제거하고 다음 라인 처리를 시작합니다.

  • x

    이는 를 포함하지 않는 행에서만 수행됩니다 age is : 10. 이 경우 현재 행을 예약된 공간에 저장합니다.

반대로 해라

나이를 다음과 같이 인쇄하고 싶다고 가정합니다.아니요10:

$ sed -n -e '/age is : 10/{x;d}' -e '/age is :/{x;p;d;}' -e x Foo.txt 
Name is : john
Name is : peggy

위의 명령은 처음에 /age is : 10/{x;d}10세 미만의 사용자를 무시하라는 명령을 추가합니다. 이제 다음 명령은 /age is :/{x;p;d;}남은 모든 기간을 허용합니다.

답변2

POSIX적으로:

$ sed -n '/age is : 10/{g
1!p
}
h
' file

현재 줄이 일치하지 않으면 이전 줄을 인쇄합니다 age is : 10.

$ sed -n '
$!N
/age is : 10/d
P
' file

답변3

이전 버퍼는 h한 줄을 저장하는 데 적합했습니다.(또는 일련의 줄)나중에 몇 가지 테스트를 통해 그것이 올바른 것으로 입증될 때까지 말입니다. 즉, 연속적이지만 연속적이지 않은 데이터 시퀀스를 처리하는 데 적합합니다.하지만순차 - 서로 붙일 수 있기 때문입니다. 그러나 두 버퍼 간에 많은 복사가 필요합니다. 이전 명령을 사용하여 일련의 줄을 작성하는 경우(추가만 하면) 나쁘지 않지만 버퍼를 H변경할 때마다 x전체 버퍼를 다른 버퍼에 복사하고 그 반대의 경우도 마찬가지입니다.

이미 연속된 일련의 행을 처리하고 컨텍스트에 따라 이를 잘라내고 싶을 때 더 좋은 방법은 보기를 사용하는 것입니다.첫 번째h- 기존 버퍼의 모습과는 다르게 -뒤에.cuonglm이 이런 일을 해요이미 그의 답변의 후반부이지만 이 논리를 두 가지 형식 중 하나로 사용할 수 있습니다.

sed '$!N;/\nage.*: 10/P;D' <infile >outfile

이는 마지막 줄이 아닌 줄의 현재 패턴 공간 N에 포함된 줄바꿈 구분 기호 뒤에 오는 확장 입력 줄을 추가한다는 점에 유의하세요. \n그런 다음 방금 가져온 라인이 패턴과 일치하는지 확인하고 일치하는 경우 패턴 공간의 첫 번째 줄에만 인쇄하므로 이전 라인만 인쇄됩니다. 마지막으로 패턴 공간의 첫 번째 줄을 삭제하고 루프를 다시 시작합니다. 따라서 파일 전체에서 한 줄을 계속 찾습니다.!$P\nD\n첫 번째불필요하게 버퍼를 교환할 필요가 없습니다.

명령을 약간 변경하면 전체 파일에 걸쳐 두 줄짜리 창을 밀어서 정확히 어떻게 작동하는지 확인할 수 있습니다. l전에 ook 명령을 추가 하겠습니다 D.

sed '$!N;/\nage.*: 10/P;l;D'

Name is : sara
Name is : sara\nage is : 10$
age is : 10\nName is : john$
Name is : john\nage is : 20$
age is : 20\nName is : Ron$
Name is : Ron
Name is : Ron\nage is : 10$
age is : 10\nName is : peggy$
Name is : peggy\nage is : 30$
age is : 30$

이것이 출력입니다. 로 끝나는 줄은 패턴 공간의 이스케이프 버전을 표준 출력으로 렌더링하는 $ook 명령의 결과입니다 . l로 끝나지 않는 줄 은 인쇄 $되지 않는 줄입니다 P. 보시다시피, 이전 라인은 P패턴 공간의 두 번째 라인( N방금 끌어온 추가 라인과 \n패턴 공간의 ewline 뒤의 라인)이 패턴과 일치하는 경우에만 인쇄됩니다.

이미 제공된 솔루션 외에도 인쇄를 위한 다른 방법을 선택할 수 있습니다.이름이전 줄나이좋아요아니요10으로 끝남:

sed -n '/^Name/N;/ 10$/!s/\nage.*//p'

...패턴 공간이 문자열로 시작하는 경우 \newline과 확장 입력 행만 추가됩니다.N이름p, 패턴 공간이 문자열로 끝나지 않는 경우에만 출력할 라인을 인쇄합니다 .10 그리고ewline 다음에 문자열을 성공적으로 바꿀 sed수 있는 경우s///\n나이그리고 패턴 공간이 끝날 때까지 이어지는 모든 것. \n편집 명령(예: ext)의 결과를 제외하고는 패턴 공간에 ewline이 있을 수 없기 때문에 N고유한이름인쇄된 줄은 바로 다음과 같습니다.나이좋아요아니요문자열로 끝남10.

위 답변에 사용된 모든 구문은 POSIX 표준입니다. 이는 sed해당 표준을 지원하는 모든 구문과 동일하게 작동해야 합니다.

관련 정보