awk, sed, grep을 사용한 그룹 입력

awk, sed, grep을 사용한 그룹 입력

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

1001   Ivanov I.I: chess 
2021   Petrov P.P: chess, football
3352   Sidorov S.S:  
1000   Putin V.V: judo
8773   Schwarzenegger A: judo, chess, football

출력은 다음과 같을 것으로 예상됩니다.

-- chess -- 
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V.
  Schwarzenegger A

답변1

이것은 질문에 지정한 대로 정확하게 작업을 수행하는 추악한 "oneliner"입니다.

for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/ <p>/' | sed 's/$/<\/p>/'; done;

그러나 나는 이 정확한 문제를 해결하는 데 도움을 주기 위해 이 글을 쓰는 것이 아닙니다. 저는 의도적으로 매우 구체적인 작업을 수행하는 부분으로 솔루션을 작성했으며 아래에는 이러한 부분이 수행하는 작업에 대한 설명이 나와 있습니다. 그러니 원한다면공부하다이 특정 문제를 해결하는 것 이상으로 이러한 도구를 사용하는 방법을 계속 읽어보세요!

비트별로 어떻게 작동하는지 살펴보겠습니다.

for tag in- 라는 이름의 새 변수를 정의합니다 tag. 이는 필요한 태그에 사용됩니다.

cat input- 이름이 지정된 파일을 읽고 input이 이름을 파일 이름으로 변경합니다.

|파이프는 일련의 명령을 통해 데이터를 얻는 재미있는 방법입니다.

cut -d: -f2- 콜론을 :구분 기호로 사용하여 두 번째 필드를 가져옵니다. 그러면 각 줄의 콜론 뒤에 텍스트가 표시됩니다.

sed 's/<\/p>//g'- 입력의 각 줄에서 닫는 단락 기호를 제거합니다.

이 시점에서 데이터는 다음과 같습니다.

 chess 
 chess, football

 judo
 judo, chess, football

다음으로 공백으로만 구성된 빈 줄을 제거해 보겠습니다. 일부 줄에는 연결된 태그가 없기 때문입니다.

sed '/^[[:space:]]*$/d'- 공백만 있는 모든 줄을 제거합니다. 엄청난!

tr "," "\\n"- 각 라벨이 별도의 줄에 표시되도록 모든 쉼표를 개행 문자로 바꾸세요.

sed 's/[[:space:]]//g'- 줄 시작 부분의 추가 공백을 제거합니다.

sort -u- 태그를 알파벳순으로 정렬하고 중복된 태그를 제거합니다. 이제 우리는 중복 없이 순서대로 모든 태그의 완벽한 목록을 갖게 되었습니다.

chess
football
judo

지금,각각이러한 태그에 대해 다음을 차례로 수행합니다.

echo "<p>-- $tag --</p>"- 지정된 대로 단락 html 태그, 두 개의 대시, 태그 이름, 두 개의 대시 및 닫는 단락 태그를 인쇄합니다.

grep $tag input- 특정 태그가 있는 행 찾기

awk '{print $2, $3}'- 정자체 이름 필드(성 + 이니셜)

sed 's/://g'- awk가 약어의 일부로 간주하는 콜론을 제거합니다.

sed 's/^/ <p>/'- 각 줄의 시작 부분에 단락 태그를 추가합니다.

sed 's/$/<\/p>/'- 각 줄 끝에 닫는 단락 태그를 추가하세요.

done;- 끝났어, 예!

결과는 다음과 같습니다.

$ for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/  <p>/' | sed 's/$/<\/p>/'; done;
<p>-- chess --</p>
  <p>Ivanov I.I</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- football --</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- judo --</p>
  <p>Putin V.V</p>
  <p>Schwarzenegger A</p>

편집: 누군가 라벨이 입력의 일부가 아니라고 언급했습니다. 이렇게 하면 상황이 약간 단순화됩니다.

$ for tag in `cat input |cut -d: -f2 |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "--$tag --"; grep $tag input | awk '{print $2, $3}' | sed 's/://g'; done; 
--chess --                                                        
Ivanov I.I
Petrov P.P
Schwarzenegger A
--football --
Petrov P.P
Schwarzenegger A
--judo --
Putin V.V
Schwarzenegger A

답변2

awk -F: '{
    sub( "[ 0-9]+", "", $1 )
    gsub( " +", "", $2 )
    cz=split( $2,comp,"," )
    for( c=1; c<=cz; c++ ) {
        if( comp[c] ) {
            if( ! allcomp[comp[c]] ) 
                fifocomp[++fifoc] = comp[c]
            allcomp[comp[c]] = allcomp[comp[c]] "  " $1 "\n" 
        }
    }
} END {
    for( c=1; c<=fifoc; c++ ) {
        print "-- " fifocomp[c] " --"
        printf "%s", allcomp[fifocomp[c]]
    }
}' file

산출:

-- chess --
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V
  Schwarzenegger A

관련 정보