일치하는 항목이 발견될 때마다 이전 줄을 인쇄하고 싶습니다. 이해 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
\n
D
\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'
...패턴 공간이 문자열로 시작하는 경우 \n
ewline과 확장 입력 행만 추가됩니다.N
이름p
, 패턴 공간이 문자열로 끝나지 않는 경우에만 출력할 라인을 인쇄합니다 .10 그리고ewline 다음에 문자열을 성공적으로 바꿀 sed
수 있는 경우s///
\n
나이그리고 패턴 공간이 끝날 때까지 이어지는 모든 것. \n
편집 명령(예: ext)의 결과를 제외하고는 패턴 공간에 ewline이 있을 수 없기 때문에 N
고유한이름인쇄된 줄은 바로 다음과 같습니다.나이좋아요아니요문자열로 끝남10.
위 답변에 사용된 모든 구문은 POSIX 표준입니다. 이는 sed
해당 표준을 지원하는 모든 구문과 동일하게 작동해야 합니다.