파일에서 문자열 "xxx"와 "yyy" 사이의 모든 문자를 표시하고 싶습니다(따옴표는 구분 기호의 일부가 아닙니다). 어떻게 해야 하나요? 예를 들어, "Hello world xxx 이것은 yyy 파일입니다"라고 입력하면 "이것은 파일입니다"가 출력되어야 합니다.
답변1
답변2
이렇게 하면 원하는 작업이 수행됩니다.
sed -e 's/xxx\(.*\)yyy/\1/'
이는 두 구분 기호 문자열이 같은 줄에 있다고 가정합니다.
답변3
이 질문은 구분 기호가 반드시 같은 줄에 있을 필요가 없는 경우에만 의미가 있습니다. 다양한 방법으로 수행할 수 있지만( 를 사용하는 경우에도 sed
) awk
더 유연합니다.
#!/bin/sh 으악' 시작 {찾기=0; /xxx/ { if(!찾기){ 발견=1; $0 = substr($0, index($0, "xxx") + 3); } } /yyy/ { if(찾기){ 발견=2; $0 = substr($0, 0, index($0, "yyy") - 1); } } { 만약 (찾기) { 인쇄; if(찾기==2) 발견=0; } } '
행에 최대 하나의 하위 문자열이 있는 경우 다음 데이터를 사용하여 간단한 테스트를 수행했습니다.
여기는 xxx yy입니다 첫 번째 두 번째 해 xxx.x 이야 xxx#yyy
그리고 다음 출력(스크립트는 "foo", 데이터는 "foo.in"):
$ 고양이 foo.in|./foo 응 첫 번째 두번째 . 엑스 #
작동 방식은 입력 데이터가 있고 $0
awk가 패턴 합계를 순차적으로 일치시켜 데이터를 인쇄하는 최종 단계로 가는 도중에 여러 가지를 변경할 수 xxx
있다는 것입니다 .yyy
$0
그런데 이 예제는 다음에서는 작동하지 않습니다.
xxxxHelloyyyxxxWorldyyy
첫 번째 일치 항목만 확인하기 때문입니다. Perl 스크립트는 awk 예제에서 사용한 것처럼 인덱싱/하위 문자열 대신 그리디 매칭을 사용하기 때문에 다른 결과를 제공합니다. 물론 Perl은 스크립트를 사용하여 동일한 작업을 수행할 수도 있습니다.
Awk(Perl과 같은)는 자유 형식이므로 명령은 다음과 같이 표현될 수 있습니다.
awk 'BEGIN{found=0;}/xxx/{if(!found){found=1;$0=substr($0,index($0, "xxx")+3);}}/yyy/{if(found){found=2;$0=substr($0,0,index($0,"yyy")-1);}}{ if(found){print;if(found==2)found=0;}}'
그러나 이는 예를 제외하고는 거의 수행되지 않습니다. 마찬가지로, sed
스크립트(줄 기반)는 몇 가지 제한 사항을 제외하고 한 줄로 결합될 수 있습니다. 마찬가지로 복잡한 스크립트는 sed
이런 방식으로 처리되는 경우가 거의 없습니다. 대신, 실제 프로그램으로 취급됩니다(참조:예).
추가 자료:
답변4
xxx
같은 줄에 있을 때와 없을 때도 yyy
작동하는 솔루션 :
cat /tmp/xxx-to-yyy| perl -ne '(/xxx/../yyy/) && print' | perl -pe 's/.*(xxx.*)/$1/' | perl -pe 's/(.*yyy).*/$1/'
별로 예쁘진 않은데...
명령줄에서 스크립트를 제공하는 것으로 -e
전환 되었습니다 . 입력 라인을 반복하게 만들고 perl
스크립트 다음에 인쇄하지만 그렇지 않습니다. 따라서 기본적으로 이것은 세 개의 Perl 루프를 통해 파일을 보냅니다.-n
-p
-p
-n
..
왼쪽 조건이 true를 반환하기 전에 false를 반환하고 오른쪽 조건이 true를 반환한 후에 false를 반환하는 범위 연산자입니다. 따라서 첫 번째 루프는 파일을 두 문자열(둘 다 포함) 사이의 줄로 자릅니다. 마지막 두 perl 명령은 xxx
이전 및 오른쪽 조건의 텍스트를 제거합니다. 후에 yyy
.