반달가면 이글루에서 백업 - http://bahndal.egloos.com/631090
댓글로 질문을 받았던 문제인데, 답변이 길어서 별도의 게시물로 작성.
문제는 대략 아래와 같다. 간단한 예시로 설명한다.
my_data.txt 파일에 3개의 항목(a, b, c)들 사이의 상관 관계가 기록되어 있는데, 형식은 아래와 같다.
# my_data.txt 내용
cat my_data.txt
a b#, c:
b a#
c a, b:
각 행의 첫번째 항목(field)은 항목 명칭이다.
각 행의 두번째 항목 이후는 첫번째 항목에 대한 상관 관계 자료다. 연관성 종류에 따라 "#" 또는 ":" 기호가 추가될 수 있다. 이 자료를 2차원 테이블로 표현하는 것이 목표다. 위의 예시를 표현하면 아래와 같이 만드는 것이 결과물이다.
a b c
-------
a| na # :
b| # na n
c| 0 : na
행과 열이 같은 값인 위치는 "na", 상관관계는 있으나 추가 기호가 없는 경우는 "0", 상관관계가 없는 경우는 "n"으로 표시하였다.
2차원 연관 배열(associative array)를 사용한다면 테이블의 위치를 인덱스로 사용해서 할당할 수 있을 것이다.
# 첫번째 행
x[a,a]="na"; x[a,b]="#"; x[a,c]=":"
# 두번째 행
x[b,a]="#"; x[b,b]="na"; x[b,c]="n"
...
문제는 항목의 수가 100개일 경우다. 수작업은 불가능하고 자동화해야 하는데, 아래와 같이 스크립트를 만들어 볼 수 있겠다.
# 연관 배열(associative array) a_arr 선언
declare -A a_arr
# 대상 파일 지정: my_data.txt
src_file="my_data.txt"
# a_arr의 값을 모두 "n"으로 초기화
col_names=`cat "$src_file" | cut -d' ' -f1 | tr '\n' ' '`
for init_first_idx in `echo "$col_names"`
do
for init_second_idx in `echo "$col_names"`
do
a_arr[$init_first_idx,$init_second_idx]="n"
done
done
# 파일을 한줄씩 읽어서 처리
while read -r rline
do
first_idx=`echo "$rline" | cut -d' ' -f1`
# 행과 열의 값이 같을 경우 "na" 설정
a_arr[$first_idx,$first_idx]="na"
# 상관관계 자료 처리
for data_val in `echo "$rline" | cut -d' ' -f2-`
do
# the second idx 값을 알기 위해 "#", ":", "," 기호 제거(sed 활용)
second_idx=`echo "$data_val" | sed 's/[#:,]//g'`
# 연관 배열에 값 할당 ("#", ":", "0")
if [[ `echo "$data_val" | grep "#" | wc -l` -eq 1 ]]
then
a_arr[$first_idx,$second_idx]="#"
elif [[ `echo "$data_val" | grep ":" | wc -l` -eq 1 ]]
then
a_arr[$first_idx,$second_idx]=":"
else
a_arr[$first_idx,$second_idx]="0"
fi
done
done < "$src_file"
# 결과 출력
for arr_key in `echo "${!a_arr[*]}" | tr ' ' '\n' | sort`
do
echo "a_arr[$arr_key]: ${a_arr[$arr_key]}"
done
echo " "
# 테이블 형태로 결과 출력
echo " $col_names"
echo " -------------"
for init_first_idx in `echo "$col_names"`
do
echo -n "$init_first_idx| "
for init_second_idx in `echo "$col_names"`
do
echo -n "${a_arr[$init_first_idx,$init_second_idx]} "
done
echo " "
done
위 스크립트에 대한 이해에 도움이 될 만한 이전 게시물들은 아래와 같다.
텍스트 파일을 한줄씩 읽어서 작업하기
리눅스 bash 스크립트에서 연관 배열 사용하기
리눅스 bash 스크립트에서 연관 배열의 인덱스/키 출력하기
'bash script' 카테고리의 다른 글
[bash:awk] awk를 이용한 분산/표준편차 계산 (0) | 2023.10.12 |
---|---|
[bash:awk] awk를 이용한 평균값 계산 (0) | 2023.10.12 |
[bash: sed] 슬래시(/)가 포함된 문자열 대체하기 (0) | 2023.10.11 |
[bash: cut] 필드 구분자(delimiter)가 없는 경우 출력 억제하기 (0) | 2023.10.11 |
[bash: $()] 역따옴표(`)를 중첩해서 사용하고 싶을 경우 (0) | 2023.10.10 |