grep 또는 egrep을 사용하여 출력 인스턴스 사이의 구분 기호로 출력 형식을 지정하는 방법이 있습니까?

grep 또는 egrep을 사용하여 출력 인스턴스 사이의 구분 기호로 출력 형식을 지정하는 방법이 있습니까?

많은 양의 데이터가 포함된 데이터 세트가 있습니다.

ID Number:  A00001
Name:       John Smith
Address:    123 Any Street
City:       AnyTown
State:      Ohio
Zip:        12345

ID Number:  A00002
Name:       Jane Doe
Address:    123 Any Street
City:       AnyTown
State:      Nebraska
Zip:        12346

ID Number:  C00003
Name:       Jim Shields
Address:    123 Any Street
City:       AnyTown
State:      Alaska
Zip:        12347

ID Number:  D11111
Name:       Mary Ellis
Address:    123 Any Street
City:       AnyTown
State:      Nevada
Zip:        12348

데이터를 추출하여 다음과 같이 분리하고 싶습니다.

ID Number:  A00001
Name:       John Smith
Zip:        12345
=========================
ID Number:  A00002
Name:       Jane Doe
Zip:        12346
=========================
ID Number:  C00003
Name:       Jim Shields
Zip:        12347
=========================
ID Number:  D11111
Name:       Mary Ellis
Zip:        12348
=========================

나는 찾을 수 있는 모든 grep 및 egrep 옵션을 시도했지만 가장 가까운 방법은 각 출력 줄 사이에 빈 줄(새 줄)을 넣는 것입니다.

답변1

grep텍스트 형식을 다시 지정하는 도구가 아닌 패턴 일치 도구입니다. 대신 sed, awk또는 같은 것을 사용하세요 perl. 예를 들어:

$ awk '/^(ID Number|Name|Zip):/;
       /^[[:blank:]]*$/ { print "=========================" }'
ID Number:  A00001
Name:       John Smith
Zip:        12345
=========================
ID Number:  A00002
Name:       Jane Doe
Zip:        12346
=========================
ID Number:  C00003
Name:       Jim Shields
Zip:        12347
=========================
ID Number:  D11111
Name:       Mary Ellis
Zip:        12348

이것은 [[:blank:]]*어떤 줄과도 일치합니다바라보다비어있는 것 같지만 실제로는 스페이스나 탭 같은 가로 공간이 들어있는데... 눈으로만 보기 힘든 부분이기 때문에 생각보다 흔히 발생합니다.

또는 Perl을 사용하십시오.

perl -l -n -e 'print if /^(ID Number|Name|Zip):/;
               print "=" x 25  if /^\h*$/' input.txt

또는 먼저 Perl RE의 "수평 공간"을 이해하는 sedGNU sed 또는 다른 sed가 있는 경우 :\h

sed -n -E -e '/^(ID Number|Name|Zip):/p; s/^\h*$/=========================/p' input.txt 

그렇지 않으면 sed를 사용하십시오.

sed -n -E -e '/^(ID Number|Name|Zip):/p; s/^[[:blank:]]*$/=========================/p' input.txt

답변2

모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.

$ cat tst.awk
BEGIN {
    FS = ":"
    split(tgts,tmp)
    for (i in tmp) {
        tags[tmp[i]]
    }
    sep = "========================="
}
$1 in tags
!NF { print sep }
END { if (NF) print sep }

$ awk -v tgts='ID Number:Name:Zip' -f tst.awk file
ID Number:  A00001
Name:       John Smith
Zip:        12345
=========================
ID Number:  A00002
Name:       Jane Doe
Zip:        12346
=========================
ID Number:  C00003
Name:       Jim Shields
Zip:        12347
=========================
ID Number:  D11111
Name:       Mary Ellis
Zip:        12348
=========================

$ awk -v tgts='City:State' -f tst.awk file
City:       AnyTown
State:      Ohio
=========================
City:       AnyTown
State:      Nebraska
=========================
City:       AnyTown
State:      Alaska
=========================
City:       AnyTown
State:      Nevada
=========================

답변3

각 섹션을 레코드로 처리하고 섹션의 각 행을 필드로 처리하면 출력에서 ​​레코드를 구분하기 위해 등호 줄을 사용하여 각 레코드의 처음 두 필드와 마지막 필드를 출력하려는 ​​것처럼 보입니다.

$ awk -F'\n' -v OFS='\n' -v RS='' -v ORS='\n=========================\n' '{ print $1,$2,$NF }' file
ID Number:  A00001
Name:       John Smith
Zip:        12345
=========================
ID Number:  A00002
Name:       Jane Doe
Zip:        12346
=========================
ID Number:  C00003
Name:       Jim Shields
Zip:        12347
=========================
ID Number:  D11111
Name:       Mary Ellis
Zip:        12348
=========================

명령줄에서는 먼저 입력 및 출력 필드 구분 기호 값을 개행 문자로 설정합니다. 이렇게 하면 입력과 출력 모두에서 필드가 별도의 줄에 표시됩니다.

그런 다음 레코드 구분 기호를 빈 문자열로 설정하면 "단락 모드"가 활성화됩니다. 즉, 하나 이상의 빈 줄로 구분된 텍스트 섹션을 단일 레코드로 읽을 수 있습니다.

그런 다음 출력 레코드 구분 기호를 등호로 설정하고 양쪽 끝에 줄 바꿈을 추가합니다.

실제 코드는 각 레코드의 첫 번째, 두 번째 및 마지막 필드를 인쇄합니다. $6대신 사용할 수도 있습니다 $NF.

관련 정보