![다른 두 열의 고유한 조합을 기반으로 열에서 그룹을 추출하는 방법](https://linux55.com/image/168865/%EB%8B%A4%EB%A5%B8%20%EB%91%90%20%EC%97%B4%EC%9D%98%20%EA%B3%A0%EC%9C%A0%ED%95%9C%20%EC%A1%B0%ED%95%A9%EC%9D%84%20%EA%B8%B0%EB%B0%98%EC%9C%BC%EB%A1%9C%20%EC%97%B4%EC%97%90%EC%84%9C%20%EA%B7%B8%EB%A3%B9%EC%9D%84%20%EC%B6%94%EC%B6%9C%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95.png)
다음과 같은 데이터가 있습니다.
Sample_1 Apples Red
Sample_2 Apples Red
Sample_3 Apples Red
Sample_4 Apples Red
Sample_5 Apples Red
Sample_6 Apples Green
Sample_7 Apples Green
Sample_8 Apples Green
Sample_9 Apples Green
Sample_10 Apples Green
Sample_11 Apples Yellow
Sample_12 Apples Yellow
Sample_13 Apples Yellow
Sample_14 Apples Yellow
Sample_15 Apples Yellow
다른 두 열에 의해 형성된 그룹의 조합을 기반으로 첫 번째 열에서 샘플을 반복적으로 추출하여 샘플 1-5, 6-10 및 11-15를 얻으려면 어떻게 해야 합니까?
내가 궁극적으로 원하는 것은 샘플 목록(위 그룹과 같은)을 다른 명령에 대한 입력으로 전달하는 것입니다. 예를 들면 다음과 같습니다.
comm -23 <(sort <all_samples.txt>) <(sort <[input from above]>) > <difference.txt>
나는 시도했다:
awk '{print $2"\t"$3}' <file.txt> | uniq
두 번째와 세 번째 열의 고유한 조합을 얻으려면 아무것도 할 수 없는 것 같습니다. 특히 첫 번째 열을 당기는 것이 정확히 필요한 것입니다.
답변1
이게 당신이 하고 싶은 일인가요?
$ awk '{vals[$2 FS $3] = vals[$2 FS $3] OFS $1} END{for (key in vals) print key vals[key]}' file
Apples Red Sample_1 Sample_2 Sample_3 Sample_4 Sample_5
Apples Green Sample_6 Sample_7 Sample_8 Sample_9 Sample_10
Apples Yellow Sample_11 Sample_12 Sample_13 Sample_14 Sample_15
아니면 이게 아닐까?
$ awk -v fruit='Apples' -v color='Green' '($2==fruit) && ($3==color)' file
Sample_6 Apples Green
Sample_7 Apples Green
Sample_8 Apples Green
Sample_9 Apples Green
Sample_10 Apples Green
답변2
다음은 입력을 구문 분석하고 필요에 맞는 전치된 데이터를 출력하는 간단한 gawk 스크립트의 예입니다.
#!/usr/bin/gawk -f
# Checks if type (column 2) or subtype (column 3) are
# different from previous line.
(type != $2) || (subtype != $3) {
# Prints the start of a new output line.
# The NR!=1 check avoids that a new line is
# printed on the first line.
printf("%s%s\t%s\t", (NR!=1)?"\n":"", $2, $3);
type=$2;
subtype=$3
}
{
# Prints all sample (column 1) values on the
# current output line.
printf("\"%s\" ", $1);
}
# prints a new line at the end of file.
END{
print "";
}
출력은 script.awk < input.lst
다음과 같습니다. script.awk
이전 스크립트는 어디에 있으며 input.lst
입력 예는 무엇입니까?
Apples Red "Sample_1" "Sample_2" "Sample_3" "Sample_4" "Sample_5"
Apples Green "Sample_6" "Sample_7" "Sample_8" "Sample_9" "Sample_10"
Apples Yellow "Sample_11" "Sample_12" "Sample_13" "Sample_14" "Sample_15"
스크립트 출력은 다음과 같이 쉽게 조작할 수 있습니다.
script.awk < input.lst | while read TYPE SUBTYPE LIST
do
echo $TYPE
echo $SUBTYPE
for ITEM in $LIST
do
echo execute some command on $ITEM where type is $TYPE and subtype is $SUBTYPE
done
done
이 스크립트는 매우 조잡하다는 점에 유의하세요. 예를 들어, 오류 처리가 없으며 공백이나 특수 문자 입력을 확인하지 않습니다.
답변3
아래 스크립트를 사용해 보았고 잘 작동했습니다.
for i in "Apples"; do for j in "Red" "Green" "Yellow"; do awk -v i="$i" -v j="$j" 'BEGIN{print "Below are table contains" " " i " and " " " j}$2==i && $NF==j{print $0}' filename; done; done
산출
Below are table contains Apples and Red
Sample_1 Apples Red
Sample_2 Apples Red
Sample_3 Apples Red
Sample_4 Apples Red
Sample_5 Apples Red
Below are table contains Apples and Green
Sample_6 Apples Green
Sample_7 Apples Green
Sample_8 Apples Green
Sample_9 Apples Green
Sample_10 Apples Green
Below are table contains Apples and Yellow
Sample_11 Apples Yellow
Sample_12 Apples Yellow
Sample_13 Apples Yellow
Sample_14 Apples Yellow
Sample_15 Apples Yellow