본문 바로가기

Linux/쉘프로그래밍

Shell Programming 기본

1.1. 문자열 처리

  • shell에서 문자열 중에 "*" or "sh" 이런 문장이 나왔을 때 echo와 같은 명령으로 문자열을 출력하려고 하면 유의해야 한다.
    original="* * * * * sh /weblogic/bea/domains/uccdomain/uccifAppRoot/demon/email/start.sh"

    (x)echo $original
    (o)echo "$original"

    (x)sed 's/"$original"/abc/g'
    (o)sed 's/'"$original"'/abc/g'

1.2. 기초 정보

#Shell
- 명령 해석기 (== 윈도우즈 탐색기)
- 시스템과 사용자간의 대화 창구 = 쉘 인터페이스

#Shell의 종류
- Bourn shell ($)
- C Shell (%)
- 기본 기능이나 동작법은 동일

#Linux 기본 shell
- GNU Bourne again shell(/bin/bash)

#Shell 의 기능
-내부 명령, 외부 명령실행 => 명령 프롬프트
-다중 프로세서 관리 => 멀티 프로세싱 시스템
-여러 명령 연결 : 파이프(|)
-입/출력 리다이렉션(>,<,>>,<<,2>)
-특수문자 해석 및 치환, 명령어 치환
-지역/환경 변수 관리
-스크립트 프로그래밍 언어 => 자동화 작업 (==Dos의 .bat파일)

#Shell의 명령 해석 과정
-shell프롬프트 : 명령 대기 상태
Eg>
#echo SHELL => echo는 뒤에 오는 문자열을 출력
SHELL
#echo $SHELL => 명령행에서 $를 보고 shell이 뒷단어를
/bin/bash 변수로 인식 => 변수내용 출력
@메타문자
- shell이 해석하는 특수한 기능을 가진 문자 => $
- 메타문자 해석 금지 => \, "", ''

#와일드 카드(문자열 대체)
@와일드 카드(문자열 대체)
- * : 0개 이상의 모든 문자와 일치(스페이스와 도트제외)
ls -al t* =>문자수에 상관없이 t로 시작하는 모든 list
- ? : 한 개의 문자와 일치
ls -al a?b =>a로 시작 b로 끝나는 세자로된 파일만 list
-[] : 괄호한에 문자와 일치, 범위 지정 a-h
ls -al [a-hA-H]*p => 첫 글자는 소문자 대문자 a-h 마지막 글자는 p로 끝나는 모든 파일

#Redirection
- Standard Input(stdin) 장치 => 키보드
- Standard Output(stdout) 장치 => 모니터
- Standard Error(stderr) 장치 => 모니터
- Re + direction
#표준 출력 Redirection
- 표준출력 장치로 가는 자료(명령의 결과)의 방향을 전환
- 메타문자: > , >>
ls /etc > conf_file : redirection으로 파일생성
ls /etc/x11 > conf_file : 기존에 있던 파일을 지우고 다시 쓰기
ls /etc/x11 >> conf_file : 기존에 있던 파일에 추가

#표준에러
- 화면에 표시되는 에러의 내용만을 리다이렉션
- 메타문자 : 2>, 2>>
gcc -c hello.c 2>error.txt
만약 에러가 발생하지 않으면 error.txt 파일은 생성않됨

#표준입력
- 키보드로부터 입력을 받을 내용을 파일등에서 입력
- 메타문자 : <, <<
sort < unsort.txt > sorted.txt : unsort를 입력해서 sorted에 저장
cat < text.txt > text.txt => file안의 내용 삭제
why: 출력 리다이렉션 기호를 만나면 출력할 내용을
지우고 다시 입력하므로
cat << end => end문자를 만나면 입력 종료

#파이프(명령어 연결)
=> 데이터를 연결
- pipe ==> 연결통로
- 파이프로 연결된 앞 프로그램의 실행결과(출력결과)를
뒤쪽 프로그램의 입력 값으로 연결해주는 역할
- 메타문자 : "|"
- 한가지 명령만으로 원하는 결과를 얻기 부족할때 다른 명령과 조합
- 사용방법 => #명령1 | 명령2 | 명령3
ls -al /bin | less
ls /bin | sort | leff = >sort 알파벳 정렬

#필터
- 표준입력으로 부터 자료를 읽어 간단한 처리후 표준출력으로
보내는 프로그램
-예:> head, tail, wc, sort, grep, awk, sed
ls /usr/bin | sort | less
cat /etc/passwd | wc =>wc는 행수 단어수 바이트 수 출력
rpm -qa | grep apache

1.2.1. 표준출력

A.
> /dev/null

B.
1> /dev/null

C.
2> /dev/null

위의 A와 B는 같은 의미입니다.

B와 C의 차이는 1과 2 차이인데,
1의 의미는 STDOUT(standard output)
2의 의미는 STRERR(standard error) 입니다.

STDOUT 은 표준출력으로, 정상적인 메시지를 출력하고
STDERR 은 표준에러로, 에러메시지를 출력합니다.

즉,
B는 표준출력을 /dev/null 로 redirection 하고
C는 표준에러를 /dev/null로 redirection 합니다.

표준출력, 표준에러 그리고 표준입력도 있는데
리눅스에서는 이것들을 "파일"이라고 부릅니다.

1.3. 기본적인 명령

1.3.1. 주석문

  • # : 주석문
  • #! : 스크립트를 해설할 인터프리터 쉘 지정 (예: #!/bin/sh)

1.3.2. 변수 사용

  • 변수를 지정할때에는 공백없이 =를 이용하면 좌변은 변수, 우변은 값이된다.
  • 변수를 사용하고자 할때에는 $를 붙여서 사용한다.

kido> var1=hello

kido> echo var1
var1

kido> echo $var1
hello

kido> echo '$var1'
$var1

kido> echo "$var1"
hello

1.3.3. 특수 변수

$# : 매개 변수의 수를 저장
$* : 매개변수 전체를 스트링으로
$$ : PID
$! : 백그라운드에서 마지막으로 실행된 작업의 PID
$@ : $*와 동일한 기능
$- : 쉑의 현재 옵션
$? : 마지막 실행된 명령어의 상태, 결과
$n : n번째 argument
  • 예제

#!/bin/sh
localVar="Hello Kido"
curPath=pwd

echo "홈 디렉토리 : $HOME"
echo "지역 변수 : $localVar"
echo "아규먼트의 개수 : $#"
echo "모든 아규먼트를 단일 라인으로 출력 : $*"
echo "현재 프로세스 아이디 : $$"
echo "아규먼트 문자열 : $@"
echo "현재 쉘 정보 : $-"
echo "마지막 실해된 명령어 상태 : $?"
echo "실행한 스크립트 명 : $0"
echo "첫번째 아규먼트 : $1"
echo "두번째 아규먼트 : $2"

  • 결과

kido>./var.sh hello kido
홈 디렉토리 : /home/kido
지역 변수 : Hello Kido
아규먼트 개수 : 2
모든 아규먼트를 단일 라인으로 출력 : hello kido
현재 프로세스 아이디 : 2311
아규먼트 문자열 : hello kido
현재 쉘 정보 : h
마지막 실행된 명령어 상태 : 0
실행한 스크립트 명 : ./var.sh
첫번째 아규먼트 : hello
두번째 아규먼트 : kido

1.3.4. 실행 결과를 변수에 저장

  • 실행 결과를 변수에 저장히기 위해서는 변수=명령문 혹은 변수=$(명령문)을 이용한다

kido>var1=$(id)
kido>echo "$var1"
uid=511(kido) gid=511(kido) group=519(kido)

kido>var2=`id`
kido>echo "$var2"
uid=511(kido) gid=511(kido) group=519(kido)

1.3.5. 파일 체크 하기

  • 두개의 파일을 체크한다.
  • 파일을 체크할때에는 [ 파일 비교연산자 파일 ]이며 [ ] 사이에는 반드시 공백이 있어야 한다.

-a : 파일 존재 여부
-b, -c, -d, -f, -h, -L, -S : 파일 유형 검사 (-f 파일인지검사, -d 디렉토리인지 검사)
-k : sticky bit 설정 유무
-r, -w, -x : 읽기, 쓰기, 실행가능 여부
-s : 파일 크기가 0보다 큰지?
  • 예제

kido>[ -s var.sh ] // var.sh의 크기가 0보다 큰지 체크한다.
kido>echo $? // 참인경우 0
0

1.3.6. 문자열 체크

  • 문자열을 비교한다.
  • [ 스트링 비교 연산자 "문자열" ]

=  : 같다
!= : 같지않다.
-z : NULL이면 참
-n : NULL이 아니면 참
  • 예제

kido>[ "hello" = "hi" ]
kido>echo $?
1

kido>[ -z "" ]
kido> echo $?
0

kido>[ -n ""]
kido> echo $?
1

* 예제2

#!/bin/sh
if [ X$1 = XPC ]
then
echo "COMPUTER"
fi

* 결과

kido>./stringTest.sh PC
COMPUTER

kido>./stringTest.sh
kido>

1.3.7. 숫자 체크

  • 숫자 비교를 수행한다. 단 소숫점 이하의 숫자는 무시되므로 유의해야한다.
  • [ "숫자" 숫자비교 연산자 "숫자" ]

-eq : 같다
-ne : 같지않다.
-lt : 작다
-le : 작거나 같다.
-gt : 크다
-ge : 크거나 같다.
  • 예제

kido>[ "3" -gt "4" ] // 3이 4보다 크다?
kido>echo $?
1 // 거짓

kido>[ "3" -lt "4" ] // 3이 4보다 작다?
kido>echo $?
0 // 참

1.3.7.1. 숫자 연산

  • 첫번째값부터 두번째값까지의 합을 구하는 소스

#!/bin/bash

if [ -z $1 ] || [ -z $2 ]
then
echo "인자가 부족합니다."
exit
fi

result=0
value=$1
while [ "$value" -le "$2" ]
do
result=$(($value+$result))
value=$(($value+1))
done
echo "$1에서 $2까지의 합은 $result 입니다."

  • 결과

[user@host user]$ ./sum.sh 1 10
1에서 10까지의 합은 55 입니다.

1.3.8. 기타 논리연산 AND, OR

  • test문에서 여러가지 조건을 검사할 경우 and, or이 필요하게 된다. 이럴때 사용되는 문
  • 주의해야 할 것은 -a나 -o를 사용할 경우 모든 연산자 사이에서는 공백을 넣어 구분해 주어야 하고, 복잡한 경우 \(, \)을 사용하여 구분해 주는것이 좋다.

-a : and 관계 연산자
-o : or 관계 연산자

* 예제

A=1
B=1
C=2
D=3

if [ \("$A" = "$B" \) -a \("$C" != "$D" \) ]
then
E=${A}${B}${C}${D}
fi

echo $E

  • 결과

kido>./andOr.sh
E=1123

1.3.9. if문

  • 조건1이 참이면 실행명령 1 실행, 조건 1일 거짓이면 실행명령2 실행

if 조건 1; then
실행명령 1
else
실행명령 2
fi

혹은

if 조건 1
then
실행명령 1
else
실행명령 2
fi
  • 주의할 점, if then 다음에 아무런 실행명령이 없으면 에러가 발생한다. 그럴때에는 then 다음에 :를 넣어주어야 한다.

if [ -f temp ]
then :
else
if [ -f temp1 ]
then
mv temp1 temp2
fi
fi
  • 예제

#!/bin/sh
input=$(echo $1 | tr a-z A-Z)
if [ "$input" = "HI" ]
then
echo "Your Input is $input"
echo "HI"
elif [ "$input" = "HELLO" ]
then
echo "Your input is $input"
echo "HELLO"
else
echo "Your input is $input"
fi

  • 결과

kido>./if.sh kido
Your input is kido

kido>./if.sh hi
Your input is HI
HI

kido>./if.sh hello
Your input is HELLO
HELLO

1.3.10. case 문

  • 판단할 조건이 많을경우 if문보다 보기 편하고, 사용하기 쉬운 분기문이다.

case 판단값 in
패턴1)
실행명령
;;
패턴2)
실행명령
;;
*) --이외의 조건 default임
실행명령
;;
esac
  • 예제

#!/bin/sh
case $1 in
start)
echo "Starting My deamon .. [OK]"
exit 0
;;
stop)
echo "Stopping My deamon .. [OK]"
exit 0
;;
restart)
echo "Stopping My deamon .. [OK]"
echo "Starting My deamon .. [OK]"
exit 0
;;
*)
exit 1
;;
esac

  • 결과

kido>./case.sh
kido>./case.sh start
Starting My deamon .. [OK]

kido>./case.sh stop
Stopping My deamon .. [OK]

kido>./case.sh restart
Stopping My deamon .. [OK]
Starting My deamon .. [OK]

1.3.11. for 문

  • 변수를 목록의 값 만큼 실행한다.

for 변수명 in 목록
do
실행 명령
done
  • 예제

#!/bin/sh

for i in 1 2 3 4 5 6 7 8 9
do
for j in 1 2 3 4 5 6 7 8 9
do
result=`expr $i \* $j`
echo "$i * $j = $result"
done
echo " "
done

  • 결과

kido>./for.sh
1 * 1 = 1
1 * 2 = 2
...

9 * 8 = 72
9 * 9 = 81

  • 예제 2 (파일 리스트를 읽어 출력하기)

A=`ls *`
for B in `echo $A`
do
echo $B
done

  • 결과

kido>fileList.sh
test.sh
kido.txt
abc.txt
data: -- 디렉토리의 의미
temp -- 디렉토리 안의 파일

1.3.12. while 문

  • 조건이 거짓일때까지 loop반복

while 조건
do
실행 명령
done
  • 예제

#!/bin/sh
i=1
result=0
while [ $i -le 10 ]
do
result=`expr $result + $i`
i=`expr $i + 1`
done
echo "1 to 10 : $result"

  • 결과

kido>./while.sh
1 to 10 : 55

  • 예제 2(무한루프 만들기)

while [ 1 ]
do
echo "Test"
done

혹은

while [ : ]
do
echo "Test"
done

혹은

while :
do
echo "Test"
done

1.3.13. until 문

  • 조건이 거짓이면 실행 명령 실행

until 조건
do
실행명령
done
  • 예제

#!/bin/sh
i=1
result=0
until [ $i -gt 10 ]
do
result=`expr $result + $i`
i=`expr $i + 1`
done
echo "1 to 10 : $result"

  • 결과

kido>./until.sh
1 to 10 : 55

1.3.14. break, continue

  • C언어와 유사하게 사용된다.

#!/bin/sh
i=0
result=0
while [ $i -le 9 ]
do
i=`expr $i + 1`
if [ $i -eq 7 ]
then
echo "breaking loop i is $i"
break
elif [ $i -eq 5 ]
then
echo "continue loop i is $i"
continue
fi
result=`expr $i + $result`
echo "result is $result"
done

  • 예제

kido>./break.sh
result is 1
result is 3
result is 6
result is 10
continue loop i is 5
result is 16
breaking loop i is 7

  • 예제 2 (yes면 계속, 아니면 종료하는 루프)

#! /bin/sh

while :
do
read x
if [ "$x" = "yes" ]
then
continue
else
break
fi
done

  • 결과

kido>./contAndBreak.sh
yes
no
kido>

1.3.15. 함수 사용하기

  • 함수를 만들고 사용한다.

함수이름() - function label
{
실행 명령
-- function body
}

함수의 반환형태
return : 가장 마지막에 수행 명령의 상태 반환
return 0 : 에러 없음
return 1 : 에러
  • 예제

#!/bin/sh
greeting()
{
echo "Hello World"
}
greeting

  • 결과

kido>./func.sh
"Hello World"

  • 예제 2 (파일 복사하는 함수)

#! /bin/sh

multicopy()
{
source=$1
while [ $# -gt 1 ]
do
cp $source $2
shift
-- 파라미터를 하나씩 좌로 쉬프트한다. (tmp1 tmp2 -> tmp2 -> tmp3의 방식으로 이동)
done
}

multicopy tmp tmp1 tmp2 tmp3

  • 결과

kido>cat multicopy.sh > tmp -- 우선 소스를 복사한다.
kido>./multicopy.sh
kido> ls
multicopy.sh tmp tmp1 tmp2 tmp3 -- 모두 동일한 소스가 들어가게 된다.

1.3.16. Debuging

  • 디버깅을 위해서는 쉘 파일 처음에 set -x를 해주면 실행될 때 단계적으로 과정을 출력해서 보여준다.

#! /bin/sh
set -x

...

1.4. 디렉토리 색상 바꾸기

-- 여기 색 정보를 수정해도 bash shell상에서는 변경 되지 않는다. --
#vi /etc/DIR_COLORS
==============================================================
57 NORMAL 00 # global default, although everything should be something.
58 FILE 00 # normal file
59 DIR 01;34 # directory 01:34
60 LINK 01;36 # symbolic link
61 FIFO 40;33 # pipe
62 SOCK 01;35 # socket
63 BLK 40;33;01 # block device driver
64 CHR 40;33;01 # character device driver
65 ORPHAN 01;05;37;41 # orphaned syminks
66 MISSING 01;05;37;41 # ... and the files they point to
==============================================================



-- bash shell 상에서 디렉토리와 기타 파일들을 다른 색으로 변경 --
#vi /etc/bashrc 를 열어서 맨 아랫쪽에 아래 구문을 적으면 된다.
==============================================================
LS_COLORS="di=01;35:or=1;40;31:*.gz=1;35:*.bz2=1;35:*.tar=1;35:*.rpm=1;35:*.tgz=1;35:*.h=1;37:*.c=1;37:*.patch=1;37"
export LS_COLORS
==============================================================
di 는 directory 의미
di = 01;35 해석
==> 앞의 수는 attribute
==> 뒤의 수는 text color, backgroundcolor, 00 은 흰색으로 표시


-- 적용 --
#source /etc/bashrc
  • attribute

    00

    none

    01

    bold

    04

    underscore

    05

    blink

    07

    reverse

    08

    concealed

  • text color

    30

    black

    31

    red

    32

    green

    33

    yellow

    34

    blue

    35

    magenta

    36

    cyan

    37

    white

  • backgroundcolor

    40

    black

    41

    red

    42

    green

    43

    yellow

    44

    blue

    45

    magenta

    46

    cyan

    47

    white

1.5. AIX 에서 이전 명령어 실행

-- 설정 --
set -o vi

-- 이전 명령 찾기 --
ESC + K

'Linux > 쉘프로그래밍' 카테고리의 다른 글

Shell 전화번호부 작성  (0) 2008.10.15
Shell 키보드 입력하기  (0) 2008.10.15
Shell 로 백업 처리하기  (0) 2008.10.15