내 파일의 데이터는 다음과 같습니다.
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()
출력합니다. 의 키를 반복하여 개별적으로 인용하고 사이에 쉼표를 사용하여 문자열 변수에 추가합니다. 그런 다음 , (중괄호 안에) 및 를 인쇄합니다.col1
col2
col3
col2
data
col1
data
col3
해당 특정 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 블록은 데이터, 서식 지정 및 인쇄를 반복합니다.