400 likes | 587 Views
4 장 . Bourne 셸. 컴퓨터공학과 강성인. Bourne 셸 기능. 내장 명령어. 리다이렉션. 프로그래밍 언어. 명령열. 변수. 시작하기. {...}. export. readonly. profile. trap. set. read. <& >&. for. case. while. if. 4.1 Bourne Shell 에 추가된 기능들. 변수를 설정하고 접근하는 방법들 조건 분기 , 루핑과 인터럽트 조작을 지원하는 내장된 프로그래밍 언어
E N D
4장. Bourne 셸 컴퓨터공학과 강성인
Bourne 셸 기능 내장 명령어 리다이렉션 프로그래밍 언어 명령열 변수 시작하기 {...} export readonly profile trap set read <& >& for case while if 4.1Bourne Shell에 추가된 기능들 • 변수를 설정하고 접근하는 방법들 • 조건 분기, 루핑과 인터럽트 조작을 지원하는 내장된 프로그래밍 언어 • 기존의 리다이렉션과 명령열 운영의 확장 • 새로운 몇 개의 내장 명령어
4.2 시작하기 • /bin/sh • sh 명령어 : 스크립트나 터미널로부터 수동적 호출 가능 • 대화형셸 • 시작시 자신의 홈 디렉토리에서 “.profile”화일을 찾음. • “.profile”의 존재 유무에 관계없이 prompt를 내보내고 사용자의 명령을 기다림 • 비대화형셸: • 어떤 시작 화일도 읽지 않음
init 터미널 포트를 열어 표준 입출력 에러방향 설정 login /bin/login 프로그램 실행 /bin/sh 실행(login shell) /etc/profile 실행 사용자 홈 디렉토리의 .profile 검사하여 실행 sh login : sikang passwd: Welcome! $_ Bourne 셸의 시작
4.3 변수 • 변수의 생성 및 할당 • 변수가 존재하면 새로운 값으로 바꾸고, 존재하지 않으면 자동적으로 만들어짐. • 새롭게 생성된 변수는 항상 지역변수. • 공백은 “ ” 로 묶어준다. • 문자열을 저장(수치도 문자열로 취급) • “=“좌우에 공백이 있어서는 안됨 {name=value}+
$ firstname=sungin lastname=kang //2개 변수의 생성 $ echo My name is $firstname $lastname My name is sungin kang $ name=sungin kang kang: 없음 $ name="sungin kang“ //문자열은 따옴표로 표시 $ echo $name sungin kang $_
변수로의 접근 1 • $name : name의 값으로 대치 • ${name} : name의 값으로 대치. 변수 이름의 일부로 번역되는 문자가 숫자가 표현식 다음에 올 때 유용 • $ verb=sing //변수할당 • $echo I like $verbing //verbing 변수는 없다 • I like • $echo I like ${verb}ing • I like singing • $_
변수로의 접근 2 • ${name-word} : 설정 되었으면 name의 값으로 대치, 그렇지 않으면 word 의 값으로 대치 • ${name+word} : name이 설정되었을 때 word만 대치 $ startDate=${startDate-"`date`"} //설정되어 있지 않으면 date 실행 $ echo $startDate 2004년 4월 6일 화요일 오후 09시 18분 34초 $ flag=1 //변수 할당 $ echo ${flag+'flag is set'} flag is set $ echo ${flag2+'flag is set'} //결과 “null” $_
변수로의 접근 3 • ${name=word} : name이 설정되지 않았으면 word를 할당하고 name의 값으로 대치 • ${name?word} : name이 설정되지 않았으면 word는 표준 에러 채널로 표시되고 그 셸은 종료. $ echo x=${x=10} //디폴트 값 할당 x=10 $ value=${x?'x not set'} //접근 성공 $ echo $value 10 $ value=${grandTotal?'grand total not set'} //미설정 grandTotal: grand total not set $_
표준 입력으로부터 변수 읽기 표준 입력으로부터 한 줄을 읽고 명시된 변수들에게 그 줄로부터 연속된 단어들을 할당한다. read {variable}+ $ cat script.sh echo "enter your name,age: \c" read name age //두 변수로 읽기 echo your name is $name echo your age is $age $ script.sh enter your name,age: Glass 20 your name is Glass //첫 번째 변수가 첫째 단어를 저장 your age is 20 // 마지막 변수가 나머지를 저장 $_
export {variable}+ • 변수의 범위 전환 • 환경변수로 범위 전환시키도록 명시된 변수들을 표시 • 환경변수는 대문자 사용 $ export //현재까지 export된 변수 표시 반출(export) LOGNAME 반출(export) PATH $ DATABASE=/dbase/db //지역변수 생성 $ export DATABASE //export $ export //export된 변수 목록 추가 반출(export) DATABASE 반출(export) LOGNAME 반출(export) PATH $ sh //서브셸 생성 $ echo $DATABASE //복사본 상속(환경변수의 특성) /dbase/db $ ^D
readonly {variable}+ • 읽기 전용 변수 • 환경변수로 전환된 변수의 읽기 전용 상태는 상속되지 않음 $ passwd=Shazam //지역변수 할당 $ echo $passwd Shazam $ readonly passwd //읽기전용변수 $ passwd=Phoombah passwd: 읽기 전용임 //수정 안됨 $ export passwd //변수를 export $ sh //서브셸 실행 $ passwd=Alasca //읽기전용변수 상태 상속 안됨 $ echo $passwd Alasca $ ^D $ echo $passwd Shazam $_
미리 정의된 지역 변수 • 일부 셸 변수들은 미리 정의 되어 있어 일반 지역 변수 명으로 사용 할 수 없다.
$ cat script.sh echo argument num : $# echo argument unit : $@ echo first argument : $1 echo second argument : $2 echo command name : $0 echo argument unit\('$*'\) : $* echo process ID : $$ $ script.sh a b c d argument num : 4 argument unit : a b c d first argument : a second argument : b command name : script.sh argument unit($*) : a b c d process ID : 9887 $_ $ sleep 1000 & 9888 $ kill $! 9888 종료됨(Terminated) $ echo $! 9888 $ ls script.sh script.sh $ echo $? 0 $ lls lls: 없음 $ echo $? 1 $
$ PS1="sh?“ // 새로운 프롬프트 생성 sh?oldIFS=$IFS // IFS의 이전 값 기억 sh?IFS=":“ // 단어 분리자를 “:”으로 변경 sh?ls:script.sh // 실행 성공 script.sh sh?string="a long \ > string“ // >는 보조 프롬프트 sh?echo $string a long string sh?PS2="???“ // 보조 프롬프트 변경 sh?string="a long \ ???string" sh?
4.4 산술 계산 • expression을 계산하여 그 결과를 표준 출력으로 보낸다. • expression은 연산자와 연산 항으로 구성되고 공백으로 분리. • 모든 셸 메타문자들은 \로 특수기능을 상실한다. expr expression ※ 계산 순서를 명시적으로 제어하기 위해서는 \( \)를 사용
$ x=1 $ x=`expr $x + 1` $ echo $x 2 $ x=`expr 2 + 3 \* 5` //* 계산후 +계산 $ echo $x 17 $ echo `expr \( 2 + 3 \) \* 5` //\( \) 먼저 계산 25 $ echo `expr \( 4 \> 5 \)` 0 //거짓이므로 0 $ echo `expr \( 4 \> 5 \) \| \( 6 \< 7 \)` 1 //참이므로 1
문자열 연산자 $ echo 'expr length "cat" ' //cat의 길이 구하기 3 $ echo 'expr Substr "donkey" 4 3' //부문자열 추출 key $ echo 'expr index "donkey" "ke" ' //부문자열 위치 4 $ echo 'expr match "smalltalk" '.*lk' ' //일치하는 문자열 길이 9
4.5 조건식 • expression이 참이면 0인 종료 코드를 돌려주고 그렇지 않으면 0이 아닌 종료 상태를 반환한다. • test라는 명령어 대신에 두 번째 형식 “[ ]”를 사용하는 경우 대괄호와 expression사이에 공백이 추가되어야 한다. test expression [ expression ]
4.6 제어구조(Case-in-esac) • 패턴에 대응하는 것을 찾아 그 패턴의 명령들을 실행하는 다중 선택형식 • expression은 문자열로 계산되는 식이고, pattern은 대표문자를 포함할 수 있음 • expression을 계산한 후 순차적으로 pattern과 비교하여 맨 처음 일치하는 패턴에 연관된 명령어 리스트가 실행된다. • 파이프 심볼(|)을 사용하여 다수의 단어들로 하나의 pattern을 형성할 수 있다. case expression in pattern { | pattern }* ) list ;; esac
$ cat menu.sh #! /bin/sh echo menu test program stop=0 while [ $stop -eq 0 ] #완료 시 까지 반복 do cat << ENDOFMENU 1 : print the date. 2,3 : print the current working directory 4 : exit ENDOFMENU echo echo 'your choice? \c' read reply echo case $reply in "1") date ;; "2"|"3") pwd ;; "4") stop=1 ;; *) #디폴트 echo illegal choice #오류 ;; esac done $ menu.sh menu test program 1 : print the date. 2,3 : print the current working directory 4 : exit your choice? 1 2007년 3월 31일 토요일 오후 06시 39분 04초 1 : print the date. 2,3 : print the current working directory 4 : exit your choice? 2 /home/sikang 1 : print the date. 2,3 : print the current working directory 4 : exit your choice? 3 /home/sikang 1 : print the date. 2,3 : print the current working directory 4 : exit your choice? 4 $
4.6 제어구조(for-do-done) • 단어 리스트 안의 각 word를 통해 변수 name의 값을 반복하며, 각 반복 후에 list에 있는 명령을 실행 • 단어 리스트가 제공 되지 않으면 $@($1,$2,...)이 사용된다. for name [ in { word } * ] do list done
$ cat for.sh #! /bin/sh for color inyellow green blue do echo one color is $color done $ for.sh one color is yellow one color is green one color is blue $_ $ cat for.sh #! /bin/sh for color do echo one color is $color done $ for.sh yellow red blue one color is yellow one color is red one color is blue $_ 단어 리스트 제공 안됨 단어 리스트 제공
False if list1 True False elif list3 list2 True list4 list5 4.6 제어구조(if-then-fi) if list1 then list2 elif list3 //여러 번 반복 가능 then list4 else //1번 이하 수행 list5 fi
$ cat if.sh #! /bin/sh echo 'enter a number: \c' read number if [ $number -lt 0 ] then echo negative elif [ $number -eq 0 ] then echo zero else echo positive fi $ if.sh enter a number: 1 positive $ if.sh enter a number: -1 negative $ if.sh enter a number: 0 zero
4.6 제어구조(until-do-done) • 일련의 명령어들이 실패되는 동안(결과가 거짓) 명령을 반복 실행한다. $ cat until.sh x=1 until [ $x -gt 3 ] do echo x=$x x=`expr $x + 1` done $ until.sh x=1 x=2 x=3 $ until list1 do list2 done
4.6 제어구조(while-do-done) • 일련의 명령어들이 성공되는 동안(결과가 참) 명령을 반복 실행한다. while list1 do list2 done
$ cat multi.sh if [ "$1" -eq "" ]; then echo "Usage: multi number" exit fi x=1 while [ $x -le $1 ] do y=1 while [ $y -le $1 ] do echo `expr $x \* $y`"\t\c" y=`expr $y + 1` done echo x=`expr $x + 1` done $ multi.sh Usage: multi number $ multi.sh 5 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25 $
4.6 제어구조(break, continue) • break : 반복문의 강제 종료 • continue : 반복문의 처음으로 분기 구구단 예제 : 입력한 숫자 까지만 구구단을 출력 $ multi2.sh enter a number: 4 1*1= 1 1*2= 2 1*3= 3 1*4= 4 1*5= 5 1*6= 6 1*7= 7 1*8= 8 1*9= 9 2*1= 2 2*2= 4 2*3= 6 2*4= 8 2*5= 10 2*6= 12 2*7= 14 2*8= 16 2*9= 18 3*1= 3 3*2= 6 3*3= 9 3*4= 12 3*5= 15 3*6= 18 3*7= 21 3*8= 24 3*9= 27 4*1= 4 4*2= 8 4*3= 12 4*4= 16 4*5= 20 4*6= 24 4*7= 28 4*8= 32 4*9= 36 $
$ cat multi2.sh #! /bin/sh echo "enter a number: \c" read stop x=1 while [ $x -le 9 ] do y=1 while [ $y -le 9 ] do echo "$x*$y=" `expr $x \* $y`"\t\c" y=`expr $y + 1` done echo if [ $x -eq $stop ] then break fi x=`expr $x + 1` done
4.6 제어구조(trap) • 번호가 붙여진 signal을 받을 때마다 셸에게 command 를 실행하도록 지시 • 여러 개의 signal이 받아들여지면 번호순으로 trap됨 • signal 번호 0이 지정되면, 셸이 종료됐을 때 command가 실행됨 trap [ [ command ] { signal } + ]
$ cat trap.sh #! /bin/sh clear count=1 trap break 2 while [ 1 -gt 0 ] do echo $count: infinite loop. sleep 1 count=`expr $count + 1` done echo echo end loop. echo $_ 1: infinite loop. 2: infinite loop. 3: infinite loop. ^C end loop. $_
4.8그 밖의 내장 명령어 • read 명령어(.) • 텍스트파일의 내용을 실행 • 실행 허가권이 필요 없음 • 파일 실행 시 현재 셸에서 실행 (파일이 설정한 모든 지역 변수가 현재 셸의 지역 변수임) • set 명령어 • shell옵션의 설정을 on또는 off시킬 수 있다. 옵션을 on 시키려면 옵션에 –를 붙이고 off 시키려면 +를 옵션에 붙인다. • 셀 프로그램을 디버깅 할 때 유용
$ cat script2.sh set -vx a.c #디버그 추적을 설정하고 $1을 덮어 쓴다. ls $1 set - #추적중지 echo goodbye $LOGNAME echo $notset set –u #미설정 변수 접근 시 오류 발생 echo $notset $ script2.sh ls $1 //-v옵션에 의한 출력 + ls a.c //-x옵션에 의한 출력 a.c //정상 출력 set - //-v옵션에 의한 출력 + set - //-x옵션에 의한 출력 goodbye sikang //정상 출력 script2.sh: notset: 파라미터가 설정되지 않음 //미설정 변수 접근 $_
4.9 리다이렉션 • 파일 기술자(file descriptor) • 유닉스에서 파일,파이프,및 소켓등 모든 입출력 객체들은 파일 기술자라는 메커니즘을 통해 커널에서 처리된다. • 파일 기술자는 0~19까지 값을 갖는다. • 특히 처음 3개의 파일 기술자는 다음과 같은 특수한 의미를 갖는다. 0:표준 입력, 1:표준 출력, 2:표준 에러 $ man ls > ls.txt 페이지를 다시 포맷 중입니다. 기다려 주십시오... 완료 $ man ls > ls.txt 2>err.txt //표준에러를 “err.txt”로 출력 $ cat err.txt 페이지를 다시 포맷 중입니다. 기다려 주십시오... 완료 $ man ls>ls.txt 2>&1 //표준에러를 표준출력으로 연계
4.9순차적 명령열 • 명령어 그룹은 서브셸에서 실행 • 중괄호를 사용한 순차적 명령열은 부모셸에서 직접 실행 • 중괄호와 명령어 사이에 공백 필수, 중괄호 닫기 전에는 “;”을 붙여 준다. $ pwd /home/sikang $ (cd /; pwd; ls | wc -l) / 38 $ pwd /home/sikang $ { cd /; pwd; ls | wc -l; } / 38 $ pwd / $