다음 명령은 특정 패턴의 첫 번째 발생까지 인쇄하지만 이후 발생은 포함하지 않는다는 것을 알고 있습니다.
sed -n '1,/<pattern>/p' <file>
sed '/<pattern>/q' <file>
예를 들어, 다음 줄이 포함된 파일이 있다고 가정해 보겠습니다.
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
this is a lion
this is a cat
이제 다음을 출력합니다.
$ sed '/fish/q' file
this is a cow
this is a goat
this is a some fish
$ sed -n '1,/fish/p' file
this is a cow
this is a goat
this is a some fish
첫 번째 줄부터 마지막 항목이 포함된 줄까지 출력을 시작하고 싶습니다.물고기즉, 내가 원하는 출력은 다음과 같습니다.
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
달성하기 위해 사용하는 방법은 무엇입니까 sed
?
답변1
이 시도:
$ tac infile | sed -n '/fish/,$p' |tac
일반적으로 sed 명령으로 실행하면 첫 번째 일치 패턴부터 입력 파일 끝까지 모든 행을 가져옵니다.
$ sed -n '/fish/,$p' file
this is a some fish
this is a fishie
this is a fish
this is a lion
this is a cat
그래서 내 해결책은 다음과 같습니다. tac
입력 파일에서 명령을 실행하면 마지막으로 일치하는 패턴이 첫 번째 패턴으로 변경됩니다. 결과 보기 tac infile
:
$ tac infile
this is a cat
this is a lion
this is a fish
this is a fishie
this is a some fish
this is a goat
this is a cow
이 tac
명령은 명령과 동일 cat
하지만 tac
파일을 역순으로 인쇄합니다.
이제 첫 번째 sed 명령을 실행하면 먼저 입력 파일의 끝까지 패턴과 일치하는 모든 줄을 얻게 됩니다. 좋다:
$ tac infile | sed -n '/fish/,$p'
this is a fish
this is a fishie
this is a some fish
this is a goat
this is a cow
좋아. 끝났어. tac
줄을 원래 순서로 복원하려면 명령을 다시 실행 하면 됩니다 .
$ tac infile | sed -n '/fish/,$p' |tac
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
완벽한!
답변2
sed
이는 매우 간단합니다. 단지 두 버퍼 간에 약간의 조정이 필요합니다. 예를 들어:
sed -n 'H;/fish/!d;$!n;x;p;G
' <<\INFILE
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
this is a lion
this is a cat
INFILE
이 명령은 H
삽입된 줄 문자 뒤의 기존 공백 에 각 줄을 추가합니다 \n
. 일치 !
하지 않는 행은 출력에서 /fish/
즉시 제거됩니다 . 이것은 우리에게 선만 d
남깁니다 . /fish/
따라서 이 줄은 n
입력된 확장 줄로 덮어쓰여집니다. 그런 다음 패턴과 h
기존 공간이 교체됩니다. H
결국 우리는 라인을 낡게 만들었습니다. 이제 패턴 공간은 H
이전 공간이고 그 반대도 마찬가지입니다. 따라서 마지막 행이 일치할 때 저장된 내용을 p
인쇄합니다 ./fish/
p
일치 항목이 발견된 경우에만 인쇄하고 그 사이에 중간 행을 저장하므로 일치 항목이 마지막으로 발생한 경우에만 도달합니다. 하지만 일치하는 항목 사이에는 가능한 한 적은 양만 저장합니다. x
버퍼가 변경될 때마다 플러시됩니다. 결과는 다음과 같습니다.
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
내가 가끔 생선을 건너뛰는 것을 알려준 Don Christy에게 큰 감사를 드립니다. 이제 만약을 대비해 플러시할 때마다 버퍼가 양쪽 끝에 푸시되고 현재 패턴 공간을 삭제하기 전에 매번 덮어쓰게 됩니다. 그것은 첫 번째나 마지막 줄의 물고기와 내가 아는 한 그 사이의 모든 줄에 적용됩니다.
제가 하고 있는 또 다른 일은 n
마지막 줄의 연장 코드를 당기는 것입니다. 이는 절대 금기 sed
사항입니다. 이 일을 도와준 Don에게 다시 한 번 감사드립니다.
더 철저한 예:
sed 'x;/./G;//!x;/fish/p;//s/.*//;x;d'
이것이 다른 문제를 더 잘 해결하기를 바랍니다. h
패턴/기존 공백은 매 사이클마다 변경됩니다. 이는 명령 끝에서 편집 대체로 인해 추가 빈 줄이 발생하는 것을 x
방지하기 위한 것입니다 . s///
따라서 버퍼가 교체되고 버퍼가 비어 있지 않은 상태로 유지되면 현재 줄이 여기에 추가되고 그 뒤에 \n
ewline 문자가 추가됩니다. 그렇지 않으면 추가 줄이 버퍼에서 나옵니다. 그렇지 않으면 버퍼가 다시 교체되고 h
이전 공간은 현재 주기 동안 비어 있게 유지됩니다. 내가 아는 한, 이 명령은 모든 빈 줄과 그 밖의 모든 것을 유지하지만 마지막 일치 항목에서 인쇄를 중지합니다.
내가 겪은 어려움 중 일부는 h
일반적으로 기존 공간에서 발생합니다. 이를 효과적으로 사용하는 유일한 방법은 기존 라인과 비교하기 위해 라인 사이클 아래 - 뒤 -에 있는 것입니다. 내가 평소에 선호하는 것은 looping 입니다 N;P;D
. 아마도 다음과 같은 것을 사용하여 이 작업을 수행할 수 있을 것입니다.
sed -ne :n -e '/fish/!N;//p;//!bn'
입력 확장 라인을 패턴 공간에 지속적으로 sed
추가 하고 레이블 로 돌아가서 재시도합니다.N
b
:n
물고기현재까지 설정된 어떤 라인과도 일치하지 않습니다. 라인 사이클의 끝에서 내용을 덤프하고 새 버퍼로 다시 시작하기 전에 일치하는 p
라인 또는 라인 시퀀스 만 인쇄합니다.fish
여기서는 의도적으로 마지막 줄을 테스트하지 않습니다. 마지막 줄이 일치하면 인쇄됩니다. 그렇지 않으면 -n
GNU의 경우 에도 sed
루프가 파일의 마지막 줄을 모두 종료할지 여부를 결정합니다.
답변3
Sed보다 짧은 awk를 사용할 수도 있습니다.
awk ' /^fish/ { print $0 }' filename.txt
어떤 사람들은 다음과 같이 쓸 수도 있습니다:
awk ' /^fish/ { print $1 $2 $3 $4 $5 }' filename.txt
$n
열을 나타냅니다 . 바로가기는 $0
전체 행을 나타냅니다.
답변4
Raku(이전 Perl_6) 사용
raku -e '$/.put if m/^ .* fish/ for lines.join("\n");'
입력 예:
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
this is a lion
this is a cat
예제 출력:
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
위의 정규 표현식은 한 단어에서 종료되며 해당 단어가 줄의 마지막 단어 fish
인 한 fish
제대로 작동합니다 . 그러나 OP가 전체를 캡처하려는 경우마지막 줄(예: fisherman
전체 단어 반환) 위의 정규식 일치자를 로 변경합니다 m/^ .* fish .*? $$ /
.