awk를 사용하여 유사한 행에 데이터 추가

awk를 사용하여 유사한 행에 데이터 추가

내 파일의 데이터는 다음과 같습니다.

field11|field12|field13
field11|field12|field23
field11|field32|field33
field41|field42|field43
field41|field52|field43
field41|field62|field63

보시다시피, 저는 2개의 ID를 갖고 field11있으며 field41다음과 같이 해당 ID가 한 번만 나타나기를 원합니다.

field11|{'field12','field32'}|field13
field41|{'field42','field52','field62'}|field43

나는 세 번째 필드가 해당 ID의 첫 번째 항목과 동일하기를 원합니다. 각 id($1)는 $3가 다르지만 첫 번째 또는 첫 번째와 두 번째 필드는 동일하게 유지됩니다. 하지만 해당 ID의 첫 번째 줄 내용을 인쇄해야 합니다. 예제에서 볼 수 있듯이 field23 대신 field13을 인쇄합니다.

나는 awk이것을 / 으로 달성하려고 합니다 sed. 나는 쉘의 기본 루프를 사용하여 이를 달성하는 솔루션을 알고 있습니다. 하지만 awk이 작업은 다른 유사한 도구에서 수행 해야 합니다 .

답변1

약간 더 긴(하지만 이해하기 쉬운) awk솔루션:

BEGIN       { FS = OFS = "|" }

function output() {
    if (FNR == 1) return
    data = ""
    for (i in col2) {
        qi   = sprintf("'%s'", i);
        data = (data == "" ? qi : data "," qi)
    }
    print col1, sprintf("{%s}", data), col3
}

$1 == col1 && !($2 in col2) { col2[$2] }

$1 != col1    {
    output()
    col1 = $1; col3 = $3
    delete col2; col2[$2]
}

END { output() }

BEGIN블록은 단순히 입력 및 출력 필드 구분 기호를 |.

이 함수는 (첫 번째 열의 ID), (두 번째 열의 고유 데이터 배열) 및 (세 번째 열의 해당 특정 ID에 대한 첫 번째 데이터 항목)에서 수집된 데이터를 가져와 output()출력합니다. 의 키를 반복하여 개별적으로 인용하고 사이에 쉼표를 사용하여 문자열 변수에 추가합니다. 그런 다음 , (중괄호 안에) 및 를 인쇄합니다.col1col2col3col2datacol1datacol3

해당 특정 ID에 대해 이전에 한 번도 본 적이 없는 두 번째 열의 항목을 찾으면 다음 블록이 실행됩니다. 두 번째 열을 의 키로 추가하기만 하면 됩니다 col2.

첫 번째 열에서 새 ID를 찾으면 다음 블록이 실행됩니다. 수집된 변수를 호출 output()하고 재설정하여 해당 새 ID에 대한 데이터 수집을 시작합니다.

END블록 에서는 output()마지막 ID에 대한 출력 데이터를 호출합니다.

프로그램은 전체 파일을 한 번에 메모리에 저장하려고 시도하지 않지만 데이터가 첫 번째 열에서 정렬되도록 요구합니다.

제공된 데이터에 대해 실행합니다.

$ awk -f script.awk file
field11|{'field12','field32'}|field13
field41|{'field42','field62','field52'}|field43

답변2

Perl의 일부 거친 부분:

perl -F'\|' -lane '
    $f2{ $F[0] }{ $F[1] } = 1;
    $f3{ $F[0] } = $F[2] if not exists $f3{ $F[0] }; 
  } END {
    for $key (sort keys %f2) {
        printf "%s|{%s}|%s\n", 
            $key, 
            join(",", map {chr(39) . $_ . chr(39)} sort keys %{$f2{$key}}), 
            $f3{$key};
    }
' file

처음 두 줄은 연관 배열을 사용하여 데이터를 축적합니다.
그런 다음 END 블록은 데이터, 서식 지정 및 인쇄를 반복합니다.

관련 정보