bash script2023. 10. 16. 08:44

 

반달가면 이글루에서 백업 - http://bahndal.egloos.com/641643

간단한 내용이지만 의외로 사용할 일이 많아서 여기에 정리해 두기로.

출력 결과의 앞쪽에 공백이 여러칸 있는 경우, sed의 문자열 대체 기능을 이용해서 제거할 수 있다. 아래의 예시를 보자.

# 기본 예시: sed에서 문자열 abc를 123으로 대체
echo "abcd" | sed 's/abc/123/'
123d

# test1.txt 파일의 내용 출력
cat test.txt
  abc
  def
  ghi

위의 경우 맨 앞의 공백이 동일하게 2칸씩이다. 이런 경우는 아래와 같이 제거해 주면 되겠다. 정규표현식(regular expression, regex)에서 행 맨처음을 나타내는 "^" 기호를 사용한다.

# test1.txt 출력, 각 행 앞쪽의 공백 2칸 제거
cat test1.txt | sed 's/^  //'  
abc
def
ghi

행 앞의 공백 칸수가 일정하지 않은 경우에는 아래와 같이 제거해 주면 된다. 개수가 불분명하므로 sed에서 문자열 대체를 지정할 때 "*" 기호를 사용한다.

# test2.txt 파일의 내용 출력
cat test2.txt
 123
   456
   789
  abc
 
# test2.txt 출력, 각 행 앞쪽의 공백 제거
cat test2.txt | sed 's/^ *//'
123
456
789
abc

728x90
Posted by 반달가면
bash script2023. 10. 16. 08:42

 

반달가면 이글루에서 백업 - http://bahndal.egloos.com/635485

리눅스 bash 스크립트에서 변수 또는 배열을 삭제하는 명령은 unset이다. 우선 변수에 대해서 아래의 예시를 보자.

# 문자열 "abc"를 변수 var에 할당
var="abc"

# 변수 var에 할당된 내용 출력
echo "$var"
abc

# 변수 var 삭제
unset var

# 변수 var에 할당된 내용 출력
echo "$var"

unset에서 지정하는 변수명 앞에 "$" 표시가 붙지 않는다는 점에 유의. 만약 "$"를 붙이면 해당 변수명이 아니라 변수에 할당된 값이 unset의 인자(argument)로 지정되기 때문이다.

배열에 대한 삭제/초기화 작업도 같은 요령이다.

우선, 리눅스 bash 스크립트에서 배열(array)을 활용하는 기본적인 방법은 이전 게시물을 참고하자. 여기로

연관배열(associative array)에 대한 기본적인 내용은 여기로

# x[1]에 abc, x[2]에 def 저장
x[1]="abc"
x[2]="def"

# 저장된 내용 확인
echo "${x[1]} ${x[2]}"
abc def

위의 예시에 대해 배열의 인덱스(index) 또는 키(key)를 출력(관련 내용은 여기로)해 보면 1과 2가 나와야 할 것이다.

# 배열의 인덱스/키 출력
echo ${!x[*]}
1 2

이제 unset 명령으로 x[1]을 삭제해 보자.

# x[1] 삭제
unset x[1]

다시 배열의 인덱스를 출력해 보면 x[1]이 사라졌음을 알 수 있다.

# 배열의 인덱스/키 출력
echo ${!x[*]}
2

인덱스를 문자열로 지정할 수 있는 연관배열도 마찬가지다.

# 연관배열 선언
declare -A xa

# 문자열 할당
xa[apple]="abc"
xa[orange]="def"

# 인덱스 확인
echo "${!xa[*]}"
apple orange

# xa[apple] 삭제
unset xa[apple]

# 인덱스 확인
echo "${!xa[*]}"
orange

배열 전체를 삭제/초기화하고 싶다면 for 반복문을 활용하면 되겠다.

# xa 전체 삭제
for idx in `echo "${!xa[*]}"`
do
  unset xa[$idx]
done

728x90
Posted by 반달가면
bash script2023. 10. 12. 20:24

 

반달가면 이글루에서 백업 - http://bahndal.egloos.com/634977

awk를 이용해서 파일에 저장된 값들의 분산(variance)과 표준편차(standard deviation)를 계산하는 방법이다. 표준편차를 계산하려면 우선 평균을 알아야 한다. awk를 이용한 평균값 계산은 이전 게시물을 참고하자. 여기로

 

전에 사용한 것과 동일한 예시를 사용해서 표준편차를 계산해 보자. data.txt 파일에 저장된 자료는 아래와 같다.

# data.txt 내용 확인
cat data.txt
john 12.35
jane -34.5
thomas 3.9

우선 평균을 계산하여 변수 mean에 할당한다.

# 평균값을 계산하여 변수 mean에 할당
mean=`awk '{ sum += $2; cnt++ } END { print sum/cnt }' data.txt`

평균을 알았으니 이제 분산을 계산할 수 있다. 분산은 각 자료값과 평균값의 차이를 제곱하여 모두 더한 후에, 이 값을 자료의 수로 나누면 된다. 자료가 전체 모집단(population)이라는 가정하에서다. 만약 자료가 모집단에서 일부를 추출한 표본(sample)이라면 합산한 값을 (자료의 수 - 1)로 나누어 준다.

awk에서 먼저 계산한 평균값을 사용해야 하므로 -v 옵션을 통해서 shell의 변수 mean에 저장된 값을 사용해야 한다. (awk의 -v 옵션에 대한 이전 게시물은 여기에)

 

# 분산을 계산하여 변수 variance_p에 할당 (모집단)
variance_p=`awk -v m="$mean" '{ sum += ($2 - m)^2; cnt++ } END { print sum/cnt }' data.txt`

-v 옵션으로 평균값을 awk 내부에서 변수 m에 할당하고, data.txt의 두번째 항목($2)과 평균값의 차이를 제곱해서 더하여 변수 sd에 할당. 자료의 수를 세기 위해 변수 cnt를 1씩 증가시킨다. 합산 작업이 끝나고 나면(END) 변수 sd를 cnt로 나눈다.

위의 계산식은 자료가 전체 모집단(polulation)이라는 가정하에서다. 만약 자료가 모집단에서 일부를 추출한 표본(sample)이라면 합산한 값을 자료의 수 cnt가 아니라 (cnt-1)로 나눈다.

# 분산을 계산하여 변수 variance_s에 할당(표본)
variance_s=`awk -v m="$mean" '{ sum += ($2 - m)^2; cnt++ } END { print sum/(cnt-1) }' data.txt`

표준편차는 분산의 제곱근을 취하면 된다. 이미 분산값을 알고 있으므로 bc를 이용해서 계산하면 되겠다. (bc에 대한 이전 게시물은 여기에)

# 표준편차 계산 - stdev_p(모집단), stdev_s(표본)
stdev_p=`echo "sqrt($variance_p)" | bc`

stdev_s=`echo "sqrt($variance_s)" | bc`

awk에도 제곱근 계산용 내부 함수가 있으므로, 분산을 계산하지 않고 awk에서 바로 표준편차를 계산할 수도 있다. 함수 이름은 sqrt로 같다.

# 표준편차 계산
stdev_p=`awk -v m="$mean" '{ sd += ($2 - m)^2; cnt++ } END { print sqrt(sd/cnt) }' data.txt`

stdev_s=`awk -v m="$mean" '{ sd += ($2 - m)^2; cnt++ } END { print sqrt(sd/(cnt-1)) }' data.txt`

728x90
Posted by 반달가면
bash script2023. 10. 12. 20:19

 

반달가면 이글루에서 백업 - http://bahndal.egloos.com/634800

awk를 이용해서 파일에 저장된 값들의 평균을 계산하는 방법이다. 우선 data.txt 파일에 아래와 같은 값이 저장되어 있다고 가정하자.

# data.txt 내용 확인
cat data.txt
john 12.35
jane -34.5
thomas 3.9

위와 같은 내용으로 저장되어 있을 때, 평균을 계산하려면 아래와 같이 가능하다.

awk '{ sum += $2; cnt++ } END { print sum/cnt }' data.txt
-6.08333

data.txt의 두번째 항목($2)을 더해서 변수 sum에 저장하고, 자료값의 수를 세기 위해 변수 cnt도 1씩 증가. 합산 작업이 끝나면(END) 합(sum)을 자료값의 수(cnd)로 나누면 평균이 된다.  

만약 파일 안에 유효하지 않은 행이 포함되어 있을 경우에는 grep을 조합하면 되겠다. data2.txt 파일이 아래와 같은 경우를 보자.

# data2.txt 내용 확인
cat data2.txt
# this is a test data file
john 12.35
jane -34.5
thomas 3.9

data2.txt의 첫번째 행이 "#" 기호로 시작하는 주석(comment)이므로 grep을 이용해서 제외하고 평균을 계산할 수 있다.

cat data2.txt | grep -v "^#" | awk '{ sum += $2; cnt++ } END { print sum/cnt }'
-6.08333

728x90
Posted by 반달가면