파일 끝까지 일치시킨 후 모든 줄을 인쇄하는 방법은 무엇입니까?


48

입력 파일 1은 다음과 같습니다.

dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

나는 other file( dog 123 4335file2에서와 같이)에서 패턴을 일치시킵니다 .

나는 라인의 패턴과 일치하고 매치 dog 123 4335라인없이 모든 라인을 인쇄 한 후 내 출력은 다음과 같습니다.

cat 13123 23424
deer 2131 213132
bear 2313 21313

라인 주소없이 사용하는 경우 패턴을 사용하십시오 (예 : 1s 라인을 일치시키고 인쇄하는 방법)?


다른 파일에 하나의 패턴 만 검색하거나 한 줄에 하나씩 포함 할 수 있습니까? 그리고 검색된 파일에서 가장 먼저 찾은 행을 검색 할 수 있습니까?
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

답변:


27

GNU를 사용하여 전체 라인을 패턴과 일치시키고 싶다고 가정하면 다음과 sed같이 작동합니다.

sed -n '/^dog 123 4335$/ { :a; n; p; ba; }' infile

표준 동등 물 :

sed -ne '/^dog 123 4335$/{:a' -e 'n;p;ba' -e '}' infile

다음 입력 ( infile)으로 :

cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

출력은 다음과 같습니다.

cat 13123 23424 
deer 2131 213132
bear 2313 21313

설명:

  • /^dog 123 4335$/ 원하는 패턴을 검색합니다.
  • :a; n; p; ba;는 입력 ( n) 에서 새 줄을 가져 와서 인쇄 ( p) 한 다음 다시 레이블 a로 분기 하는 루프입니다 :a; ...; ba;.

최신 정보

다음은 요구 사항에 더 가까운 대답입니다 (예 : file2의 패턴, file1에서 grepping).

tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1

포함 된 grep 및 cut은 file2의 패턴을 포함하는 첫 번째 행을 찾습니다.이 행 번호에 1을 더한 후 꼬리에 전달하고 더하기 1은 패턴이있는 행을 건너 뜁니다.

첫 번째 경기가 아닌 마지막 경기에서 시작하려면 다음과 같습니다.

tail -n +$(( 1 + $(grep -n -f file2 file1 | tail -n1 | cut -d: -f1) )) file1

모든 버전의 tail이 더하기 표기법을 지원하지는 않습니다.


이것은 sed에서 n과 p 명령의 첫 번째 예입니다. sed를 너무 멀리 가져가는 느낌이 들지 않습니다. (내 간단한 테스트에서) sed -n '/^dog 123 4335$/ { :a; p; n; ba; }' infile(p와 n이 전환 된)에도 일치하는 줄이 성공적으로 포함 된 것 같습니다.
요시야 요더

26

합리적으로 짧은 파일 grep만 있으면 작동 할 수 있습니다.

grep -A5000 -m1 -e 'dog 123 4335' animals.txt

5000은 "합리적으로 짧음"에 대한 나의 추측입니다 grep. 첫 번째 일치 항목 을 찾아서 다음 5000 행과 함께 출력합니다 (파일에는 그 수가 많지 않아도 됨). 일치 자체를 원하지 않으면 잘라 내야합니다. 예 :

grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2


첫 번째는 아니지만 마지막 일치는 구분 기호로 원하지 않으면 다음을 사용할 수 있습니다.

tac animals.txt | sed -e '/dog 123 4335/q' | tac

이 라인은 라인의 animals.txt역순으로 읽고 라인을 포함하여 라인을 포함하여 출력 dog 123 4335한 다음 다시 올바른 순서로 복원합니다.

결과에 일치하는 것이 필요하지 않은 경우 꼬리를 추가하십시오. 종료하기 전에 버퍼를 삭제하기 위해 sed 표현식을 복잡하게 만들 수도 있습니다.


필자의 테스트에 따르면 GNU grep 3.0은 컨텍스트 후 (지정된 값에 관계없이) 132 줄 이상을 출력하지 않습니다.
ruvim

22

실제로 Aet3miirah의 답변을 대부분 사용 하고 alexey의 답변 은 선을 탐색 할 때 훌륭합니다 (또한 작동합니다 less). OTOH, 나는 다른 접근 방식을 정말로 좋아합니다 (이것은 뒤집힌 Gilles의 답변입니다 :

sed -n '/dog 123 4335/,$p'

-n플래그 와 함께 호출되면 sed기본적으로 더 이상 처리하는 행을 인쇄하지 않습니다. 그런 다음 /dog 123 4335/파일 끝까지 일치하는 행에서 명령을 적용하라는 2- 주소 형식을 사용 합니다 (로 표시 $). 해당 명령은 p입니다. 현재 행을 인쇄합니다. 따라서 이것은 "일치하는 모든 줄을 /dog 123 4335/끝까지 인쇄합니다"를 의미 합니다.


3
dog여기서는 원하지 않는 행을 인쇄합니다 .
Stéphane Chazelas 2016 년

1
이것은 가장 좋은 답변처럼 보이며 내 경우에는 효과가 있지만 일치하는 줄을 건너 뛰도록 조정해야합니다.
Pavel Šimerda

1
sed -n '/ 개 123 4335 /, $ p'| sed '1d'는 개 라인을 제거합니다
Kemin Zhou

1
sed -n '/dog 123 4335/,$p' | tail -n +2또한 일치를 제거합니다
gilad mayani

15
sed -e '1,/dog 123 4335/d' file1

파일에서 패턴을 읽어야하는 경우 sed 명령으로 대체하십시오. 파일에 sed 패턴이 포함 된 경우 :

sed -e "1,/$(cat file2)/d" file1

파일에 찾을 리터럴 문자열이 있으면 모든 특수 문자를 인용하십시오. 파일에 한 줄이 있다고 가정합니다.

sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1

하위 문자열이 아닌 전체 줄이 일치하도록하려면 패턴을로 묶습니다 ^…$.

sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1

6
패턴이 첫 번째 줄에 있으면 작동하지 않습니다. GNU sed0,/dog.../d그 점을 가지고 있습니다.
Stéphane Chazelas 2016 년

14

$ more +/"dog 123 4335" file1


4
또한 작동합니다 less.
brandizzi

3
터미널에서 영리하지만 실제로 다른 것과 같이 파이프하면 작동하지 않습니다 tac.
jcomeau_ictx

나는 이런 식으로 사용하고, $ 더 + / 파일 1 >> 파일 2 "내 말과 일치"
AMB

1
아마도 POSIX 7에서 +대체되었을 것 -p입니다 : pubs.opengroup.org/onlinepubs/9699919799/utilities/more.html util-linux 2.20.1에서는 아직 구현되지 않았습니다. 그리고 이것은 또한 인쇄 skipping..및 추가 줄 바꿈 (stderr에 기대할 수 있으므로 좋을 수도 있습니다).
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

그때 이후로 상황이 바뀌었을까요? 내 의견은 3 관련
투표를 받았으므로

11

awk:

awk 'BEGIN {getline pattern < "other file"}
   NR == 1, $0 ~ pattern {next}; {print}' < "input file"

5

awk를 사용하는 한 가지 방법 :

awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}'  file2 file1

여기서 file2는 검색 패턴을 포함합니다. 먼저, file2의 모든 내용이 배열 "a"에 저장됩니다. file1이 처리 될 때 모든 행이 배열에 대해 검사되고 존재하지 않는 경우에만 인쇄됩니다.


OP는 패턴을 따르는 모든 줄을 출력하려고한다고 생각합니다.
Thor

@Thor : 지적 해 주셔서 감사합니다. 지금 업데이트하십시오.
Guru

잘했다 :).
Thor

5

입력이 바람직한 일반 파일 인 경우 :

GNU로 grep:

{ grep  -xFm1 'dog 123 4335' >&2
  cat; } <infile 2>/dev/null >outfile

sed:

{ sed -n '/^dog 123 4335$/q'
  cat; } <infile >outfile

GNU grep은 / 승이라는 -m옵션이 경기에서 입력을 종료합니다 - 그리고 그것 떠날 것이다 (lseekable) 입력 즉시 시점 이후가 마지막 경기를 발견 디스크립터를. 따라서 grepw /를 호출 -m1하면 파일에서 패턴의 첫 번째 발생을 찾은 후 파일 cat에서 패턴의 첫 번째 일치 이후의 모든 항목을 stdout에 쓸 수 있는 정확한 위치에 입력 오프셋을 남겨 둡니다 .

심지어 GNU없이 grep당신은 호환 POSIX 승 / 똑같은 일을 할 수 sed- sed q이 입력이, 실행하는 권리 곳 오프셋 떠날 지정 UITS. GNU sed는 이런 방식으로 표준을 준수하지 않으므로 스위치를 sed사용하여 호출하지 않으면 위의 작업은 GNU에서 작동 하지 않을 수 -u있습니다.


sed여기에 설명 된 스트림 공유 는 표시된 자유 형식 및 조건부 협력 워크 플로우에 대해 특별히 (그렇지만 참조 된 표준은 sed이에 따라 유틸리티로서 구체적으로 예 를들 수 있지만 ) 아닙니다 . 특히, 모든 표준 유틸리티 는 다음 판독기의 처리에 전혀 영향을주지 않으면 서 입력 스트림의 커서 위치를 협력하고 공유하기위한 것입니다. grep -q이 작업을 수행해야합니다. grep입력에서 일치하는 것이 발견되면 조용히 돌아와야하며 기본적으로 나머지 입력은 소비하지 않아야합니다.
mikeserv

4

두 번째 파일에 패턴을 저장하지 않고 주제의 질문에 대한 나의 대답. 내 테스트 파일은 다음과 같습니다.

$ cat animals.txt 
cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

GNU sed :

 $ sed '0,/^dog 123 4335$/d' animals.txt 
 cat 13123 23424 
 deer 2131 213132
 bear 2313 21313

펄 :

$ perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313

파일에 패턴이있는 Perl 변형 :

$ cat pattern.txt 
dog 123 4335
$ perl -ne 'BEGIN{chomp($p=(<STDIN>)[0])};print unless 1../$p/;' animals.txt < pattern.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313

2

Wth ed:

ed -s file1 <<< '/dog 123 4335/+1,$p'

이것은 하나의 print 명령을 here-string의 ed로 보냅니다 . 인쇄 명령의 범위 는 파일 끝 ( ) 까지 일치 1 ( +1) 로 제한됩니다 .dog 123 4335$


1

임시 파일을 만들지 않고 csplit사용 가능한 경우 다음과 같이 작동합니다.

sh -c 'csplit -sf"$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2

참고 file1는 입력 파일이며 file2패턴 파일입니다 (질문에 나와 있음).

위 명령의 긴 형식은 다음과 같습니다.

sh -c 'csplit --quiet --prefix="$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2

즉,

csplit --quiet --prefix="file1_" "file1" "%^$(cat "file2")%+1" && cat "file1_00"

csplitprefix위 의 플래그가 없으면 파일이 만들어집니다 xx00(접두어는 xx이고 접미사는 00). 위의 플래그로 파일을 만듭니다 file1_00. quiet플래그가 없으면 출력 파일 크기 (결과 파일의 크기)를 인쇄합니다.


0

awk가 명시 적으로 허용되지 않기 때문에 'cat'이 일치한다고 가정 한 내 제안은 다음과 같습니다.

awk '$0 ~ /cat/ { vart = NR }{ arr[NR]=$0 } END { for (i = vart; i<=NR ; i++) print arr[i]  }' animals.txt

0

파일 끝까지 일치시킨 후 모든 줄을 인쇄하는 방법은 무엇입니까?

그것을 넣는 또 다른 방법은 "첫 번째 줄에서 일치하는 줄까지 모든 줄을 삭제하는 방법"이며 다음과 같이 쓸 수 있습니다 sed.

sed -e '1,/MATCH PATTERN/d'

1
유일한 문제는 패턴이 첫 번째 줄에있을 때입니다.
don_crissti


결정하기 위해 여기에위원회가 필요하다고 생각합니다.
poige

1
@poige : nah, 당신은 같은 대답을 덜 포괄적으로 제공합니다
Thor

@don_crissti, sed -e '0,/MATCH PATTERN/d'그럼 어때?
Velkan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.