'시스템 &네트워크 관리'에 해당되는 글 3건

3장. 쉘 프로그래밍 문법 

 

학습목표

 

매개변수와 쉘 변수를 이해하고 활용한다.

연산자들을 이해하고 활용한다.

조건문과 반복문을 이해한다

 

 

1. 매개변수(파라메터)

 

쉘 변수에는 세가지 유형이 있으며 이는 매개 변수로 알려져 있다. 그종류는 키워드 매개 변수, 위치 매개변수, 특수 쉘 매개변수 등이다.

 

1) 키워드 매개 변수

키워드 매개변수명은 알파벳 문자나 _ (밑줄) 문자로 시작 되어야 한다. 그리고 그 다음에는 알파벳이나 밑줄문자의 임의의 숫자가 올 수 있다. 그 값들은 다음과 같이 기록함으로써 키워드 매개변수에 배정된다.

변수=값 변수=값 ...

 

2) 위치 매개 변수

쉘 프로그램이 실행될 때마다 프로그램명은 변수 $0에 배정되고, 명령 라인에 타이프된 인수들은 변수 $1, $2, $3 ...에 배정된다. 위치 매개변수들 set 명령으로 값을 배정 받을 수 있다. $9 이상의 매개변수는 ${nn}으로 표현할 수 있다.

Examples: 
$ cat hi 
print hello $1 
$ hi there world 
hello there 

3) 특수 매개 변수

$#     프로그램에 전달된 인수들의 수 또는 set문 실행에 의해 세트된 매개 변수들의 수 
$*     $1, $2, $3 ...과 같은 모든 위치 매개변수들을 집단적으로 참조 
$@     $* 과 같이 위치 매개변수들을 집단적으로 참조 
$0     실행중인 프로그램 이름 
$$     실행중인 프로그램의 프로세스 번호 
$!     실행을 위해 백그라운드로 보내진 마지막 프로그램의 프로세스 번호 
$?     백그라운드로 실행되지 않은 마지막 명령의 종료 값 
$-     현재 설정된 옵션값 


2. 매개변수 치환

 

가장 간단한 경우로서, 매개변수의 값은 달러표시($)를 가진 매개 변수를 선행함으로써 접근될 수 있다. 매개 변수의 치환은 파일명 치환전에, 그리고 명령 라인이 인수로 분리되기 전에 쉘에 의해 수행된다.

 

$parameter 또는 ${parameter}

매개변수의 값을 치환한다
$ print $PWD ${11} $$ 
/usr/dgk arg11 1234 
$ file=test_f 
$ cp $file ${file}x 

$ ls -x 
$ test_f test_fx

 

${parameter:-value}

parameter의 값이 null이 아닌 경우 그값을 치환하고, null인 경우에는 value값만을 치환. 
$ EDITOR=/bin/ed 
$ echo ${EDITOR:-/bin/vi} 
/bin/ed 
$ EDITOR= 
$ echo ${EDITOR:-/bin/vi} 
/bin/vi 
$ echo $EDITOR 
$

 

${parameter:=value}

parameter값이 null이 아닌경우 그값을 치환하고, null인 경우 value값을 치환하고 그것을 parameter에 대입. 
$ unset x 
$ typeset -u x 
$ print ${x=abc} 
ABC 

$ BOOKS= 
$ : ${BOOKS:=$HOME/books} 
$ echo $BOOKS 
/usr/kys/books 
$ : ${BOOKS:=tester} 
$ echo $BOOKS 
/usr/kys/books 
$

 

${parameter:?value}

parameter 값이 null이 아닐경우 그값을 치환. 그렇지 않으면 value을 표준 에러에 기록하고 빠져나옴. 
만약 value가 생략되어 있으면 parameter와 메서지를 출력프로그램에서 요구되는 변수들이 모두 설정되었는지 또는 무효가 아닌지의 여부를 알아보기위해 쉽게 사용하여 체크할수 있다.

$ print ${foo?} 
ksh: foo: parameter null or not set 
$ BOOKS= 
$ : ${BOOKS:?"No BOOKS file"} 
No BOOKS file

 

${parameter:+value}

parameter가 null이 아닐 경우 value를 치환.  null인 경우 아무것도 치환하지 않음. 
$ set a b c 
$ print ${3+foobar} 
foobar 

$ toption= 
$ echo options: ${toption:+ "T mode"} 
options: 
$

 

${#parameter}

매개변수의 길이를 치환 
$ HOME=/home/klog 
$ print ${#HOME} 
10

$

 

${#array[*]} , ${#array[@]}

배열의 요소들의 수를 치환 
$ unset x 
$ x[1]=5 x[3]=8 x[6]=abc x[12]= 
$ print ${#x[*]} 
4

 

${parameter#pattern}

매개변수의 값을 치환하며 이때 pattern과 부합되는 왼쪽 부분은 제거된다. 쉘 화일명 치환문자들(*,?,[..],@,!)을 사용할 수 있다. 
$ cd $HOME/src/cmd 
$ print ${PWD#$HOME/} 
src/cmd 
$

 

${parameter##pattern}

가장 큰 pattern과 부합되는 왼쪽 부분은 제거된다. 
$ x=/one/two/three 
$ print ${x##*/} 
three 
$

 

${parameter%pattern}

pattern과 부합되는 오른쪽 작은 부분이 제거된다. 
$ x=file.c 
$ print ${x%.c}.o 
file.o 
$

 

${parameter%%pattern}

pattern과 부합되는 오른쪽 큰 부분이 제거된다. 
$ x=foo/fun/bar 
$ print ${x%%/*} 
foo 


3. 파일 입출력

 

1) 파일 열고 닫기

exec 명령을 아무런 아규먼터 없이 사용하여 현재 환경에서 파일을 열고 닫을 수 있으며, I/O 방향재설정 방법을 사용하며 이때 파일디스크립터 값은 0-9까지 사용할 수 있다.

Examples: 
exec 3< foo  <- foo을 파일디스크립터3 으로 지정하여 읽기위해 
open 
$ exec 3<&- <- 파일디스크립터3 을 close 



4. 다큐먼트, 반환값

 

1) 다큐먼트

문자 #로 단어가 시작된다면 셀은 라인의 나머지를 주석으로 취급하고 ksh이 실행하지 않는다

Examples: 
$ cat samp_1 
# This is comment line 
# pwd 
ls -x        # display listing of the directory 
$ samp_1 
samp_1 samp_2 samp_3 samp_4 samp_5

$

 

2) 반환값

각각의 명령어는 반환값을 가진다. 명령어의 반환값은 조건 명령이나 순환명령에서 많이 사용된다. 반환값은 0에서부터 255의 값을 가진다.

반환값 0 은 정상적인 종료인 경우의 값이며 조건이나 순환명령어에서 TRUE로 사용되는 값이다. 그 이외의 모든 다른 값은 FALSE로 취급된다.

반환값 1은 명령의 실행이 실패한 경우 129-160은 명령어가 신호를 수신하고 종료한 경우에 발생되는 값이다.

ksh에서는 $? 변수에 가장 최근에 종료된 명령어의 반환값이 저장된다.

 

5. 병렬 프로세스 기능

병렬프로세스 기능은 동시에 실행되면서 상호간에 통신하고 동기화를 하는 프로세스간의 상호 작용 기능을 제공한다. 병렬프로세스의 시작은 명령어 라인의 끝에 "|&" 을 추가하므로서 구현할 수 있다.

기본적으로 병렬 프로세스의 표준입력은 그 프로세스의 부모 프로세스의 표준 출력과 연결되며, 병렬 프로세스의 표준 출력은 그 프로세스의 부모 프로세스의 표준 입력과 연결된다.

cat /etc/passwd |& 
while true 
do 
if [ -z "$FLINE" ] 
then 
  exit 0 
else 
  read -p FLINE 
fi 
echo $FLINE 
done 




6. 쉘 스크립트 실행 방법

1) . Script ( Dot Command )

 

도트 명령은 지시된 파일이 마치 그 파일로 부터의 라인들이 그지점에서 타이프 된 것처럼 쉘에 의해 판독되고 실행되도록 한다. file은 실행하도록 하는 것이 아니라 다만 읽기 쉽게 한다.

Examples: 
$ cat > .profile 
export PS1='$PWD> ' 
export PATH=$PATH:$HOME 
^d 
$ . .profile 
/home/edu01> _ 
-> 변경된 .profile의 내용을 로그아웃, 로그인 순서를 그치지 않고 현재 쉘에서 실행하여 사용자 환경을 지정할 수 있다.

 

2) ksh script_filename

 

서브쉘을 생성하여 그 쉘이 스크립트를 읽어서 실행하도록 한다. 이 경우 script_filename 파일이 실행 퍼미션이 지정되어 있지 않아도 된다.

Examples: 
$ cat > test_sub_shell 
echo "test execution of shell script file " 
echo $PWD 
^d 

$ ls -l test_sub_shell 
-rw-r--r-- 1 edu01 other 54 Jan 29 10:00 test_sub_shell 
$ ksh test_sub_shell 
test execution of shell script file 
/home/edu01 
$

 

3) chmod +x script_filename

 

script 파일에 실행 퍼미션을 설정하여 실행한다.

Examples: 
$ chmod +x test_sub_shell 
$ ls -l test_sub_shell 
-rwxr-xr-x 1 edu01 other 54 Jan 29 10:00 test_sub_shell 
$ test_sub_shell 
ksh: No such file or directory 
-> 현재 디렉토리 경로가 PATH에 설정되어 있지 않다. 
$ export PATH=$PATH:. 
-> 현재 디렉토리를 PATH 환경변수에 설정한다 
$ test_sub_shell 
test execution of shell script file 
/home/edu01 
$

 

7. 파일과 문자 테스트 연산자

 

test 명령이나 [ ... ] 연산 결과 TRUE로 반환 받는 조건이다.

1) 파일연산자

-r     file 프로세스에 의해 판독가능한 파일 
-w     file 프로세스에 의해 기록 가능한 파일 
-x     file 프로세스에 의해 실행 가능한 파일 
-f     file 보통 파일 
-d     file 디렉토리 
-c     file 문자 특수 파일 
-b     2file 블록 특수 파일 
-p     file 파이프 파일 
-u     file 파일이 SUID(집합사용자 확인) 비트세트를 가진 경우 
-g     file 파일이 SGID(집합그룹확인) 비트 세트를 가진 경우 
-k     file sticky bit이 설정된 파일 
-s     file 비제로 길이를 가진 파일 
-L     file 심볼릭 링크 파일 
-O     file 파일의 주인이 effective user id인 경우 
-G     file 파일의 그룹이 effective user id인 경우 
-S     file socket 형태의 특수 파일인 경우 
-t     file file descriptor가 어떤 단말기와 연관된 개방된 파일 디스크립터인 경우 


2) 스트링 연산자

string              스트링이 널이 아닌 경우 
-n string           스트링이 널이 아닌경우 
-z string           스트링이 널인 경우 
string1 == string2   string1 과 string2 가 같은 경우 
string1 != string2 string1 과 string2 가 같지 않은 경우

 

3) 정수 비교 연산자

int1 -eq int2       int1 이 int2 와 같은 경우 
int1 -ge int2       int1 이 int2 와 같거나 그보다 큰경우 
int1 -gt int2       int1 이 int2 보다 큰경우 
int1 -le int2       int1 이 int2 와 같거나 작은 경우 
int1 -lt int2       int1 이 int2 보다 작은 경우 
int1 -ne int2       int1 이 int2 와 같지 않은 경우

 

4) 부울 연산자

!expr               expr이 FALSE 
expr1 -a expr2      expr1이 TRUE, 그리고 expr2가 TRUE 
expr1 -o expr2      expr1이 TRUE 혹은 expr2가 TRUE 


Examples: 
$ test -x file -a ! -d file 
-> file이 실행 가능하고 디렉토리가 아닌 경우 
$ test "x$1" = xabc 
-> $1이 abc인 경우 
$ [ "x$1" = xabc ] 
-> $1이 abc인 경우 
$ test ! \( -w file -o -x file \) 
-> file 이 쓸 수 있거나 실행 가능한 파일이 아닌경우 
$ [ ! ( -w file || -x file ) ] 
-> file 이 쓸 수 있거나 실행가능한 파일이 아닌경우 



8. 내장된 정수 연산

1) 정수 연산

 

일반적인 대부분의 수식 연산을 ksh 에서는 지원하고 있다. 다음은 ksh에서 지원 되는 연산자들이다.

            단항 - 
           NOT 
           논리부정 
* , / , %    곱하기, 나누기, 나머지 
+ , -        더하기, 빼기 
<< , >>      왼쪽 시프트, 오른쪽 시프트 
< , > , <= , >=     비교 
== , !=      동등, 비동등 
            그리고 
            배타적 또는 
            또는 
&&            논리적 and 
||            논리적 or 
            배정 



2) let 명령

 

Korn쉘은 expr 명령없이 정수 연산을 수행하기 위한 메커니즘을 제공하고 있는데 그것이 let 명령이다. let은 쉘에 내장되어 있기 때문에 계산을 위한 새로운 과정을 만들거나 찾거나 프로그램을 로딩할 필요도 없다. let의 형식은

$ i=100 
$ let i = i + 1 
$ echo $i 
101 

$ let ' i = i + 1 ' 'j = j + 10'

개별적인 식들이 중간에 공백으로 가지고 있다면 인용부호로 묶어서 사용해야하며 이것은 수식 쉘로부터의 *, &, <, > 와 같은 문자들이 가지는 특별한 의미를 제거하는 부가적 효과를 가진다.

$ let 'i = ( i + 10 ) * j '

둥근 괄호를 이용하여 수식을 그룹화할 수도 있다.

 

3) (( expression ))

 

(( expression )) 은 let "expression" 과 같은 의미이다. 쌍으로된 둥근 괄호를 이용하여 let에 대한 대안적 형식을 취할수 있다.

$ (( i = i * 5 )) 
$ (( i >= 0 && i <= 100 ))

 

4) expr

 

expr 명령을 사용하여 수식 계산을 실행한 후에 변수에 그 값을 지정한다.

Examples: 
$ aa=10 
$ aa=`expr $aa + 10` 
$ echo $aa 
20 
$

 

5) integer variable

 

수식계산에 사용되는 변수를 정수로 선언하여 일반적인 형태의 수식계산 방식을 ksh에서 사용하도록 지정한다. 하지만 이렇데 지정된 변수는 반드시 정수 값만 가질수 있다.

Examples: 
$ integer aa 
$ aa=100 
$ aa=aa+1 
$ echo $aa 
101 
$ aa="test a integer variable" 
ksh: aa: bad number 
$


9. 배열

Korn쉘은 제한된 배열 능력을 제공한다. 배열은 1차원으로 512요소를 가지며, 배열의 인덱싱은 0에서 시작하고 511까지 지정할수 있다.

배열의 요소는 한쌍의 각괄호( [ ] ) 안에 넣어진 정수값으로 된 색인첨자와 함께 호출되는 것으로 자신이 요구하는 만큼 요소에 값을 할당하여 사용한다.

$ arr[0]=hello 
$ arr[1]="some text" 
$ arr[2]=/home/dgk/memos

 

배열로부터 값을 불러오는 방법은 배열의 이름과 각 괄호안에 원하는 요소의 번호를 넣고 그것을 ${ }에 넣어 사용한다.

$ echo ${arr[0]} 
hello 
$ echo ${arr[2]} 
/home/dgk/memos 
$ echo $arr 
hello 
-> 첨자가 없는 경우 요소 0이 이용된다. 
$ echo $arr[1] 
hello[1] 
-> { }을 사용하지 않고 출력한 경우 예상치 않은 결과 값을 출력한다. 

$ echo ${arr[*]} 
hello some text /home/dgk/memos 
-> 배열에 들어있는 모든 내용을 불러 온다 

$ echo ${#arr[*]} 

-> 배열 arr에 있는 요소들의 갯수. 이때 수는 실제 요소의 갯수가 아니고 가장 큰 첨자 + 1 한 값이 출력된다. 이 값은 배열안에 다음 요소를 저장하기 위한 첨자로 사용된다. 

$ arr[10]=foo 
$ echo ${arr[*]} 
hello some text /home/dgk/memos foo 
$ echo ${#arr[*]} 
11 
-> 사용자가 정수 명령을 배열명에 선언해 줌으로써 Korn쉘에게 정수 배열을 선언하게 한다. 
$ integer arr 
$ arr[0]=100 
$ arr[1]=50 
$ (( arr[2] = arr[0] + arr[1] )) 
$ echo ${arr[2]} 
150 



배열구성요약

${array[i]} 요소 i 값을 치환 
$array 첫번째 요소 array[0]값을 치환 
${array[*]} 모든 요소값을 치환 
${#array[*]} 요소들의 수를 치환 
array[i]=value value을 array[i]로 치환

 

10. 함수 정의

 

ksh에서의 function명령은 name ( ) { ....; } 형식으로 선언된다. 기능을 분류하거나 순환적으로 일어나는 일들을 하나의 변수 형식으로 지정하여 불러 사용할 수 있도록 한다.

 

function identifier 

       compound-list 

identifier( ) 

       compound-list 
}

 

Examples: 등록된 사용자수를 세는 nu 라는 함수를 정의한다. 
$ function nu 
> { 
> who | wc -l 
> } 
$ nu 
13 


$ cat funt1 
function check_yesno 

 typeset -l reply 
 while true 
 do 
 read -r "reply?$1? " || return 1 
 case $reply in 
       y|yes} return 0;; 
       n|no) return 1;; 
       *) print 'please answer y or n';; 
 esac 
 done 

while check_yesno 'Do you want to continue? ' 
do 
 foobar 
done 
$

 

일반적으로 정의된 함수는 서브쉘에 보내지지 않는다. 하지만 typeset이라는 명령을 사용하여 함수정의를 export 시킬 수 있다.

$ typeset -fx funtion-name 
-> function-name을 주지 않으면 엑스포트된 함수들의 명단을 출력한다. 

$ typeset -f -> 정의된 함수의 리스트를 출력한다. 
funcrion nu 

who | wc -l 

$

 

함수정의 삭제

함수정의를 삭제하기 위해 -f 옵션을 가진 unset명령을 사용한다.

$ type nu 
nu is a function 
$ unset -f nu 
$ type nu 
ksh: nu: not found 



11. 변수의 속성 정의

매개변수의 종류는 앞에서 키워드 매개변수, 위치매개변수, 특수매개변수로 나누어 설명하였다. 이런 각각의 변수는 하나 또는 그 이상의 특성을 정의할 수 있으며 typeset 이라는 명령어를 사용하여 변수의 특성을 on/off 하거나 설정되어 있는 내용을 리스트할 수 있다.

 

Command: typeset [-options] vasriable


Options:

 

-u Uppercase      소문자를 대문자로 변환한다. -l 옵션은 자동적으로 off된다

$ typeset -u x=abc 
$ print $x 
ABC

 

-l Lowercase      대문자를 소문자로 변환한다. -u 옵션은 자동적으로 off 된다.

$ typeset -l x=ABC 
$ print $x 
abc

 

-i or -ibase Integer    정수 변수로 정의된다. base는 수의 진법 정의

$ integer x=6 
$ typeset -i8 y=x+x 
$ print $y 
8#14

 

-L or -Lwidth Left-justified        앞에오는 공란들을 왼편 자리 맞춤시키고 스트립 시킴. width가 비제로로 정의 되어 있으면 자리수를 width로 설정한다. -R옵션은 자동적으로 off된다.

$ typeset -L3 x=abcd y 
$ y=3 
print "$y-$x" 
3 -abc

 

 

-LZ or -LZwidth Strip Leading Zero       앞에오는 제로들은 스트립되고 왼편으로 자리 맞춤한다.

$ typeset -LZ3 x=abcd y 
$ y=03 
print "$y-$x" 
3 -abc

 

-R or -Rwidth Right-justified       오른편 자리 맞춤시키고 스트립시킴. width가 비제로인 경우 자리수를 width 로 설정.

$ typeset -R3 x=abcd y 
$ y=3 
$ print "$y-$x" 
3-bcd 

-Z or -Zwidth Zero-filled 
-RZ or -RZwidth Zero-filled

-Z만 설정된 경우 -L 옵션이 굛 되어있지 않다면 오른편로 자리 맞춤 시키고 스트립시킨다. width가 비제로 값이면 자리수를 width로 설정한다. 만약 처음의 비공란 문자가 숫자이면 0으로 채워진다.

$ typeset -Z3 x=abcd y 
$ y=3 
$ print "$y-$x" 
003-bcd

 

-r Read-only      변수가 읽기전용으로 설정되어 있다면 그 변수값을 변경하려 하면 에러 메세지를 출력하고 변경이 불가능하다.

$ typeset -r foo=bar 
$ foo=nobar 
ksh: foo: is read only 
$ unset foo 
ksh: foo: is read only

 

-x Exported        모든 변수에 값이 설정되면 자동적으로 현재 환경에 값을 배당한다.

$ typeset -x foo=bar 
$ export foo=bar 

12. 패턴

 

[ . . . ] 부호     문자들을 정의하여 그중 어느 하나의 문자와 일치하는 패턴 정의할수 있다. ' - ' 부호를 사용하여 범위를지정 할수 있다. ' ! ' 부호를 사용하여 역으로 매치 시킬수도 있다.

$ ls 
chap1 chap10 chap11 chap2 chap3 chapa chapb chapc 
$ ls chap[123] 
chap1 chap2 chap3 
$ ls chap[12][01] 
chap10 chap11 
$ ls chap[!2-4] 
chap1 
$ ls chap[1-3] 
chap1 chap2 chap3

 

? 문자       어떤 문자이든 상관없이 한 문자와 매치 된다

$ ls chap? 
chap1 chap2 chap3 
chapa chapb chapc

 

* 문자       어떤 문자든 0번 또는 그 이상과 매치

$ ls chap* 
-> chap 으로 시작되는 모든 스트링 
$ ls x*y 
-> x로 시작하고 y로 끝나는 모든 스트링

 

?(pattern[|pattern]...) 패턴         0번 또는 한번 발생되는 pattern과 매치

$ ls para?([345]|99)1 
-> para1, para31, para41, para51, para991 과 매치

 

*(pattern[|pattern]...) 패턴         0번 이상 발생되는 pattern과 매치

$ ls para*([0-9]) 
-> para, para뒤에 어떤 숫자라도 붙어 있는 스트링과 매치

 

+(pattern[|pattern]...) 패턴         1번 이상 발생되는 pattern과 매치

$ ls para+([0-9]) 
-> para뒤에 숫자가 붙어 있는 모든 스트링과 매치

 

@(pattern[|pattern]...) 패턴        정확히 한번 발생되는 pattern과 매치

$ ls para@(chute|graph) 
-> parachute, paragraph 과 매치

 

!(pattern[|pattern]...) 패턴         pattern에 정의된것을 제외한 모든것과 매치

$ ls para!(*.[0-9]) 
-> para로 시작하고 .숫자로 끝나지 않는 모든 스트링과 매치 


13. 조건문

[ [ test-expression ] ] 또는 [ test-expression ] 기호

test 명령을 대신하여 테스트하는데 사용할 수 있다. 
$ [ [ foo > bar && $PWD -ef . ] ] && print foobar 
foobar

 

1) if . . . then . . . else . . . fi

if 는 일반적으로 3가지 패턴으로 사용할수있다.

형식1:

if test -f $1 
then 
  echo $1 exist 
fi

형식2:

if test -f $1 
then 
echo $1 exist 
else 
  echo $1 does not exist 
fi 

형식3:

if (( score < 65 )) 
then grade=F 
elif (( score < 80 )) 
then grade=C 
elif (( score < 90 )) 
then grade=B 
else grade=A 
fi

Examples:

if print 'Please enter your name: \c' ; read -r name 
then if mail "$name" < mailfile 
     then : 
     else print "Cannot mail to $name" 
     fi 
else print 'end-of file'
     exit 1 
fi

 

2) case

case word in 
[ ( ) pattern [ | pattern.... ] ... ] compound-list ;; ] 
. . . . 
esac

word와 매치되는 pattern을 찾아서 해당되는 compound-list를 실행한다.

Examples:

$ cat case1 
case $x in 
-d*) dflag=1;; 
-e*) eflag=1;; 
"") print -r -u2 - "x must have a value";; 
*) if test ! -r "$x" 
   then print -r - "$x: no read permission" 
   fi ;; 
esac

$ cat case2 
read -r line 
case $line in 
[$1]*) : ;; # ok 
*) print 'Line must begin with one of: $1" 
   exit 1;; 
esac 



14. 반복

 

1) for 문

 

for identifier [ in word .... ] 
do compound-list 
done

word의 개수만큼 do와 done사이의 명령어들을 반복적으로 실행한다

Examples: 
$ cat for1 
for i in apple banana mango 
do 
  echo "$i\t" 
done 

$ for1 
apple banana mango 

$ cat for2 
for i in *   ## 현재 디렉토리의 모든 파일 
do 
if test -d "$i" 
then print -r - "$i" 
fi 
done

 

다음 예제는 트럼프 놀이를 쉘 스크립트로 작성한 것이다. 한번 <Enter> 키를 칠 때 마다 카드 번호를 한 장씩 출력해준다. 총 7장의 카드를 출력해준다.

$ cat for3 
integer i=0 ; typeset -u card 
echo "Gamer I : 이름을 입력하시오: \c" 
read gamer01 
echo "Gamer II : 이름을 입력하시오: \c" 
read gamer02 
echo "카드를 섞고 있습니다" 
for suit in clubs diamonds hearts spades 
do 
  for n in ace 2 3 4 5 6 7 8 9 10 jack queen king 
  do 
  card[i]="$n of $suit" 
  i=i+1 
  done 
done 
echo "게임을 시작하겠습니다" 
for gamer in $gamer01 $gamer02 
do 
  echo "$gamer: \c" 
  i=0 
  while [ $i -le 7 ] 
  do 
    read 
    echo " ${card[RANDOM%52]} \t" 
    i=i+1 
  done 
  echo 
done



 

2) select문

 

select identifier [ in word .... ] 
do compound-list 
done

 

나열하는 word를 화면에 메뉴 형태로 표준 출력 화면으로 출력해 주고, 표준 입력으로부터 무한 반복으로 값을 입력 받는다. 값을 입력 받기위해 프롬프트를 출력해 주는데 디폴트 프롬프트는 '?' 이다. 프롬프트는 환경변수 PS3에서 지정할 수 있다.

Examples:

$ cat select1 
PS3='Please enter a number: ' 
select i in add delete modify list exit 
do 
  case $i in 
  add|modify) 
    print Select editing file 
    break;; 
  delete) 
    print Select removing job;; 
  list) 
    print Select display job;; 
  exit) 
    print Select exit job 
    print Good-bye 
    exit ;; 
  *) print 'Invalid number';; 
  esac 
done

$ select1 
1) add 
2) delete 
3) modify 
4) list 
5) exit 
Please enter a number:_ 

3) while문

 

while test문 또는 명령어 실행 
do compound-list 
done

 

while 반복문은 test문 또는 명령의 실행결과가 참(true)인 동안 루틴을 반복적으로 수행한다.

Examples:

$ cat while1 
while read -r line 
do 
  print -r - "$line" 
done 

$ cat while2 
while [ $line -le $maxline ] 
do 
  echo >> $BUFFER 
  lines=`expr $lines + 1` 
done

 

$ cat while3 
while true 
do 
  read name 
  if [ ${name}x = x ] 
  then 
    break 
  fi 
done

 

4) until 문

 

until test문 또는 명령어 실행 
do compound-list 
done

 

test문 또는 명령 실행결과가 거짓(false)인 경우 루틴을 반복 수행한다.

 

Examples:

$ cat until1 
until cc -c foo.c 
do vi foo.c 
done

$ cat until2 
until who | grep klog >/dev/null 
do 
echo waiting 5 seconds 
sleep 5 
done 
echo klog has logged on

$ cat until3 
until false 
do 
  read name 
  if [ ${name}x = x ] 
  then 
    break 
  fi 
done 

15. 흐름 제어

 

1) break [ n ]

 

이 명령의 실행은 가장 안쪽 n개의 for, while, until 루프의 실행이 즉시 종료시키고 빠져 나오며 루프다음의 명령을 계속 실행한다.

 

Examples:


$ cat break1 
for i in * 
do
  for j in foo bar bam 
  do 
     if test "$j" = "$i" 
     then 
        break 2 
     fi 
  done 
done



2) continue [ n ]

 

for, while, until 루프안에서의 이명령의 실행은 continue 다음에 오는 임의의 명령들이 skip 되도록 한다.

 

Examples:

 

$ cat continue1 
for i in * 
do 
  if test -d "$i" 
  then continue 
  fi 
  print -r - "$i is not a directory" 
done 



16. 쉘 프로그래밍 응용

1) vi with backup the file

 

vi 편집기를 호출하여 파일을 편집하여 저장하기전 이전의 파일을 filename.bak 파일에 저장하도록 하는 쉘 스크립트를 작성한다.

 

$ cat vvi 
#!/usr/bin/ksh 

if [ $# -le 0 ] 
then 
vi 
exit 
fi 
cp $1 ${1}.tmp 
vi $1 
if cmp -s $1 ${1}.tmp 
then 
  rm ${1}.tmp 
else 
  cp ${1}.tmp ${1}.bak 
  rm ${1}.tmp 
fi

 

2) newcat

 

출력용 필터인 newcat 을 생성한다. 내용의 각 라인에 라인번호를 붙여서 23개 라인씩 출력한다.

 

$ cat newcat 
#!/usr/bin/ksh 
if [ $# -lt 1 ] 
then 
  echo "Usage Error: newcat filenames... " ; exit 
fi 
for filename in $* 
do 
  integer count=1 
  integer page=1 
  exec < $filename 
  echo "Filename : $filename\t\tPage: $page " 
  while read line 
  do 
    if [ $count -eq 22 ] 
    then 
       echo "--More-- <Press Return> " 
       read 
       echo "\f" 
       page=page+1 
       echo "Filename : $filename\t\tPage: $page " 
    fi 
    echo "$count\t$line" 
    count=count+1 
   done 
done

 

3) exec_check 실행 점검 스크립트

 

program_01 이라는 프로그램을 실행하는 스크립트를 작성한다. 이미 이 프로그램이 실행중이라면 30초간 대기하면서 이미 실행중인 프로그램의 실행종료를 대기한다. 대기중 실행종료가 확인되면 프로그램을 실행시킨다. 30초가 초과되면 타임아웃으로 인식하고 메시지를 출력하고 스크립트를 종료한다.

 

$ cat exec_check 
#!/usr/bin/ksh 

trap "echo off > ex_check_file; echo "인터럽트 수신/종료"; exit 200" 2 
if [ $# -ne 1 ] 
then 
  echo "실행할 프로그램명이 입력되지 않았습니다" 
  echo "USAGE: exec_check program-name" 
  exit 
fi 
if [ ! -f ex_check_file ] 
then 
  echo off > ex_check_file 
fi 
integer count=0 
while read e_flag < ex_check_file; [ e_flag = 'on' ] 
do 
  echo "$1 프로그램이 실행중입니다. 프로그램 종료 대기중..." 
  sleep 5 
  count=count+1 
  if [ $count -eq 6 ] 
  then 
    echo "TIME OUT...." 
    echo "$1 프로그램이 아직 실행중입니다" 
    echo "잠시후 다시 실행하여 주십시오" 
    echo "스크립트를 종료합니다" 
    exit 
  fi 
done 
echo on > ex_check_file 
$1 
echo off > ex_check_file 
echo "$1 프로그램 실행을 정상 종료합니다" 


4) 웹으로 finger을 실행하게 하는 CGI 프로그램

 

#!/bin/sh !/usr/bin/ksh 
FINGER=/usr/bin/finger 
echo Content-type: text/html 
echo 
if [ -x $FINGER ] 
then 
  
if [ $# -eq 0 ] 
  
then 
    
cat << EOM 
    
<HTML>
    <HEAD><TITLE>Finger Gateway</TITLE></HEAD>
 
    
<BODY> 
    
<H1>Finger Gateway</H1> 
    
<ISINDEX> 
    
This is a gateway to "finger". Type a user@host combination in your browser's search dialog.<P> 
    
EOM 
  
else 
    
echo \<PRE\> 
    
$FINGER "$*" 
    
echo \</PRE\> 
  
fi 
else 
  
echo Cannot find finger on this system. 
fi 
cat << EOM 
</BODY></HTML> 
EOM

블로그 이미지

오픈이지 제로킴

시큐어코딩 교육/컨설팅 전문가 그룹

2장. 정규식과 유틸리티들

 

학습목표

   정규식에 대한 이해 
   grep 

   awk 
   sed

 

1. 정규식에 대한 이해


grep,awk,sed,vi,perl등과 같은 명령어들을 패터처리 언어에서 사용하는 패턴에 대한 특정 규칙을 정규식(Regular Expression)이라고 부른다. 다시 말해서 패턴이란 "규칙적으로 기술된 문자열" 이라고 설명 할 수 있고 이런 규칙들을 표현하는 형식중의 한 방법이 정규식이다.

다음은 샘플 데이터 파일과 egrep 명령을 이용하여 정규식을 하나씩 설명하겠다.

 

<샘플 파일> 
$ cat sampfile 
This is sample data file 
Hello This is Kim. 
I'm so happy 
Test100 
test200 
Are you unhappy ?

 

1) " ^ " : 행의 시작과 부합

$ grep "^H" sampfile 
Hello This is Kim.

 

2) " $ " : 행의 끝과 부합

      $ grep "happy$" sampfile 
      I'm so happy

 

3) " * " : 임의의 0개 이상의 문자와 부합

$ egrep "e*" sampfile 
This is sample data file 
Hello This is Kim. 
I'm so happy 
Test100 
test200 
Are you unhappy ? 
$ egrep "ee*" samplefile 
This is sample data file 
Hello This is Kim. 
Test100 
test200 
Are you unhappy ? 
$ egrep "ppp*" sampfile 
I'm so happy 
Are you unhappy ?

 

4) " ? " : 임의의 0 또는 1개의 문자와 부합

$ egrep "pp?" sampfile 
This is sample data file 
I'm so happy 
Are you unhappy ? 

5) " + " : 임의의 1개 이상 문자와 부합

$ egrep "pp+" sampfile 
I'm so happy 
Are you unhappy ?

 

6) " . " : 임의의 한문자와 부합

$ egrep "y.." sampfile 
Are you unhappy ?

 

7) " \< " : 단어의 시작과 부합

" \> " : 단어의 끝과 부합 
$ egrep "happy" samplfile 
I'm so happy 
Are you unhappy ? 
$ egrep "\<happy\>" sampfile 
I'm so happy 
$ egrep "happy\>" sampfile 
I'm so happy 
Are you unhappy ?



 

8) " [문자들] " : 문자들에 포함되는 하나의 문자와 부합

" ^[문자들] " : 문자들에 포함되는 문자들을 제외한 하나의 문자와 부합 
$ egrep "^[A-Z]" sampfile 
test200 
$ egrep "^[^A-Z]" sampfile 
This is sample data file 
Hello This is Kim. 
I'm so happy 
Test100 
Are you unhappy ? 
$ egrep "[0-9]$" sampfile 
Test100 
test200

 

9) 정규식과 부합하는 문자의 반복횟수

\{숫자\} : 정확히 지정된 숫자만큼 반복 
\{최소값,최대값\}: 최소값부터 최대값까지 횟수 만큼 반복 
ex) a\{1\} a가 정확히 한번 team , happy, goal 
a\{1,\} a가 한번이상 반복 team. aang, aaaang 
a\{2,5\} a가 2번이상 5번 이하 반복 aa, aaa, aaaa, aaaaa 

10) " \( 패턴 \) " : 내부 표현식을 만든다.

패턴을 하나의 문자 처럼 사용한다. 
" \숫자 " : 숫자번째 내부 표현식에 부합된 문자열을 다시 참조한다. 
$ egrep '\([A-Za-z0-9].*\)\(:.*\)\{4\}:/export/home/\1:' /etc/passwd 
결과> /etc/passwd 파일안에서 사용자의 login명과 기본 디렉토리명이 같은 사용자를 검색하여 출력한다.

 

11) " \ " : 정규식의 메타 문자가 아닌 문자 자체로 해석

$ egrep "\.$" sampfile 
Hello This is Kim. 

2. awk

awk 은 설계자인 Aho, Weingrger, Kernighan의 첫글자로 명명되어진 패턴검색과 처리 기능을 가진 인터프리티드 프로그래밍 언어로서 필터링, 치환, 간단한 리포팅 작업을 제어할수 있다.

 

1) "awk" 형식

awk 프로그램은 세부분으로 구성되어 진다.

BEGIN Section : 파일을 읽기전에 실행 
Pattern Statment Section : 파일의 각 레코드 라인을 읽어들일 때 마다 실행 
END Section : 파일을 다 읽어들인 뒤 실행

BEGIN { statements ….} 
/pattern expression / { statements  .... } 
END { statements… }
 

여러개의 statement를 한 라인에 쓸때는 statement ; statement 의 형식으로 기술한다. 

2) awk 명령어 실행 방법

 

"awk" 프로그램을 명령어 상에서 입력하는 경우 
$ awk '{print $0 }' datafile .... 
단일인용문( ' ' ) 안에 프로그램을 기술한다. 데이터 파일을 정의하지 않으면 표준 입력으로부터 데이터를 입력 받는다.

awk 프로그램을 파일로 작성하는 경우는 
$ awk -f awk-program-filename data-filenames

ex) 
$ awk ' BEGIN { print "awk 프로그램 실행 연습입니다" } ' 

$ awk '{ print $1, $2 } ' data1 
100 200 
300 400 
500 600 

$ cat ex01 
# This is sample file 
BEGIN { 
print "Hello, I'm Kim " 
exit } 

$ awk -f ex01 
Hello, I'm Kim



3) 레코드

레코드는 입력된 파일의 한 줄을 말한다. 라인 전체의 내용은 $0 변수명으로 사용되며, 입력된 레코드 번호는 NR 이라는 변수로 표시 된다.

4) 필드

입력된 레코드에서 스페이스 또는 탭으로 구분되는 문자들을 말한다. 각각의 필드는 $1,$2,$3,....$n 으로 필드위치에 따라 변수명으로 표기되며 현재 필드값은 NF 변수로 표시된다.

5) 변수

위치변수 는 필드 또는 레코드를 나타낸다
$0 : 현재 입력된 레코드를 나타내는 변수 
$1 : 현재 입력된 레코드의 첫 번째 필드를 나타내는 변수 
$n : 현재 입력된 레코드의 n번째 필드를 나타내는 변수

재정의 변수는 입력된 레코드의 구성과 크기에 대한 정보를 제공한다
NR : 레코드 수 
NF : 필드 수 
FS : 필드 구분 문자 
RR : 레코드 구분 문자 
OFS : 출력 필드 구분 문자 
ORS : 출력 레코드 구분 문자 
FILENAME : 현재 입력된 파일 이름 
OFMT : 출력 인쇄 형식

사용자 정의 변수는 프로그램의 어느 곳에서도 사용자가 정의하여 사용 할 수 있으며, 숫자 또는 문자열 값을 가진다. 초기화 하지 않으면 자동적으로 null(0) 문자를 가진다.

ex) 
$ cat data1 
100 200 
300 400 
500 600 
$ cat ex02 
BEGIN { OFS="------" } 
{ print $1,$2 } 

$ awk -f ex02 data1 
100------200 
300------400 
500------600 

$ cat ex03 
{ x = $1 + $2 
y = y + x } 
END { print y } 

$ awk -f ex03 data1 
1600 


6) 패턴 과 연산자

 

패턴의 형식은 egrep과 유사한 형식을 가진다. 정규식을 사용하여 패턴을 구성할 수 있으며 패턴은 "/ /" 형식으로 지정한다. 
"/ /,/ /" 형식을 사용하여 패턴으로 범위를 지정할 수 있다.

ex)

$ cat ex04 
$2 ~ /^[0-9]+$/ { print $2 } 
-> 두 번째 필드가 숫자로만 구성되어 있으면 두 번째 필드값을 출력 
$ awk -f ex04 data1 
200 
400 
600 

$ cat ex05 
$0 ~ /[Ee]nd/ { print "end of", FILENAME } 

-> 읽어 들인 레코드의 값이 End 또는 end이면 "end of data1" 과 같은 형식으로 출력 
$ cat ex05_1 
/Begin/,/End/ { total += $1 } 
END { print "Total = " total }

연산자는 관계연산자, 패턴 연산자, 산술연산자, 지정 연산자, 복합지정연산자, 증감연산자 가 있다. 
관계연산자는 숫자 또는 스트링 값을 비교할 때 사용한다.

==            같다 
!=           같지 않다 
>             크다
            작다 
>=            크거나 같다 
<=            작거나 같다

ex)

NF != 5 { print "필드수가 5개가 아님"} 
$1 >= 10000 { print "첫번째 필드값이 10000 보다 크거나 같다" } 
$1 >= "s" { print " 첫 번째 필드가 s 보다 뒷문자(tuvw..)이다"} 
$1 < $2 { print "두번째 필드 값이 첫 번째 필드 값보다 크다"}

 

패턴연산자는 스트링 패턴과의 일치 여부를 비교할 때 주로 사용 된다.

            패턴과 일치 
!~           패턴과 같지 않다.

 

ex) 
$1 !~ /^[0-9]+$/ { print "첫번째 필드가 숫자가 안니다" } 
$2 ~ /korea/ { print "두번째 필드값이 korea 이다"}

 

산술연산자는 수식 계산에 사용된다 
            더하기 
            빼기 
            곱하기 
            나누기 
            나누어서 남은 나머지

 

지정 연산자는 오른쪽 값을 왼쪽 변수에 대입한다 
            지정연산 
ex) a = 10

 

복합 지정 연산자는 산술연산자와 지정연산자를 결합해서 사용한다 
+= , -=, *=, /=, %=

ex) a += 5 : a = a + 5 와 같은 문장이다.

증감 연산자는 값을 1씩 증가하거나 감소 시킬 때 사용한다

++           1 증가 
--           1 감소

ex) 
$ cat ex06 
END { a = 0 
print "a++ = ", a++ 
print "a-- = ", a-- 
exit 
}

$ cat ex07 
BEGIN { a = 0 } 
$1 > 100 { a++ } 
END { print "첫번째 필드의 값이 100보다 큰 경우는 ", a, "번입니다" }
$

$ awk -f ex07 data1 
첫번째 필드의 값이 100보다 큰 경우는 2 번입니다

 

7) 출력문

print 문은 출력하고자하는 문자열은 "출력내용" 의 형식으로, 변수값은 변수명을 사용하여 출력한다. 
" , " (쉼표)는 "print"문 안에서 필드를 구분한다. "" 사이의 문자열은 하나의 필드로 취급된다. 
출력방향을 조정하기위해 " > " 문자와 " >> " 문자를 사용할수 있다. 출력될 파일이름은 인용부호("")안에서 사용한다.

ex) 
$ cat ex08 
{ print $1,$2 > "sample"} 

$ awk -f ex08 data1 
$ cat sample 
100 200 
300 400 
500 600

"printf" 문을 사용하여 출력 양식을 지정할 수 있다. 
사용형식은 printf "format",expression1, expression2,..... 이다. 
format에서 변환사양은 % 기호를 붙여서 표시한다

%d            십진수 
%o            8진수 
%x            16진수 
%s            문자열 
%f            소수 
%e            지수를 사용한 소수 
%g            %f,%e중 짧은 형태의 출력을 사용한다.

ex) 
$ cat ex09 
$1 ~ /^[0-9]+$/ { printf "첫번째 필드 값은 %d 입니다\n",$1 } 

$ awk -f ex09 data1 
첫번째 필드 값은 100 입니다 
첫번째 필드 값은 300 입니다 
첫번째 필드 값은 500 입니다 
$

 

파이프(|)를 사용하여 " print"문의 출력을 UNIX 시스템 명령어의 입력으로 사용할 수 있다. awk 안에서 유닉스 명령과 인수를 사용하는 경우는 인용부호(" ")로 묶어서 사용한다.

$ cat ex09 
END { print " Pipe Test ...Is it OK? " | "mail guest" } 

$ awk -f ex08 data1 
$ login guest 
Welcome to guest account 
You have mail 

8) 프로그래밍 언어 구조 제어문들

 

" if " 문

ex)
{ if ( $1 < 100 && $2 > $3 ) 
{ print "첫번째 필드값이 100보다 작고 두 번째 필드값이 세 번째 필드값 보다 큽니다" } 
}

ex) 
{ if ( $1 > 100 || $2 >100 ) 
{ print "첫번째 필드값이 100보다 크거나 두 번째 필드값이 100보다 큽니다" } 
}

 

" while " 문

{ i = 1 
while ( i <= NF ) 
{ print "필드수가 1개보다 작거나 같습니다" } 
}

 

" for " 문

ex) 
$ cat ex10 
{ for ( a = 1 ; a <= NF ; a++ ) print NR,a ,$a } 
$ awk -f ex10 data1 
1 1 100 
1 2 200 
2 1 300 
2 2 400 
3 1 500 
3 2 600 
$

 

" break "문은 순환문의 수행을 중지 시키고 순환문 밖의 문장을 수행한다


" continue "문은 순환문의 수행을 중지하고, 순환문의 처음 조건을 테스트한다.


" next " 문은 다음 입력 레코드를 읽어 들이고 프로그램 수행은 패턴문의 처음을 수행한다.


" exit " 문은 프로그램 실행을 종료한다

 

ex) 
$ cat ex11 
{ for ( n = 1; ; n++ ) 
{ if ( n <= NF ) { print NR, n, $n 
  continue } 
  break 
} } 

$ cat ex12 
NF > 2 { print NR, NF; next } 

$ cat ex13 
$1 > 100 { print NR, " $2= ", $2, "$2값 오류" 
exit 99 } 
$

 

9) awk에서 많이 사용되는 함수들

 

" length " 함수는 주어진 문자열의 문자 개수를 반환한다. length 함수에 인수가 없으면 현재 입력 레코드의 문자수를 반환한다.

$ cat ex14 
{ print NR, "입력된 문자열의 문자수는 " , length, "개입니다" } 
$

$ cat ex15 
{ print NR, "첫번째 필드의 문자수는 ", length($1), "개입니다" } 
$

 

" substr " 함수는 지정한 문자열에서 원하는 개수 만큼의 문자들을 추출하여 반환한다

$ cat ex16 
BEGIN { 
print substr("Happy Birthday",7,9) 
exit }

$ awk -f ex16 
Birthday

 

" index " 함수는 문자열에서 지정하는 문자열이 있는 위치를 나타낸다. 문자열에서 지정한 문자열이 포함되어 있지 않은 경우는 0 값을 반환한다.

$ cat ex17 
BEGIN { 
print index("Hello This is Kim","This") 
exit 
}

$ awk -f ex17 

$

 

" sprintf " 함수는 printf함수와 사용방법이 유사하지만 출력의 방향이 지정연산자의 왼편에 있는 변수명이다.

$ cat ex18 
{ var = sprintf("출력연습 : 첫 번째 필드 : %d ",$1) 
print var 

$

$ awk -f ex17 data1 
100 
300 
500 
$

 

3. sed

 

sed는 stream editor의 약어이며 문자를 스트림으로 나타나는 입력을 수정하거나 편집하는데 사용되는 툴입니다. 유닉스에서 제공하는 다른 편집기와의 차이점은 원본 파일을 변경시키지 않고 명령이 실행 되는 필터 기능을 가지고 있는 것입니다. 그래서 변경된 내용을 보존하기 위해서는 적절한 조치가 필요합니다.

1)   "sed" 명령어 실행 형식

sed [-n][-e edit_command][-f command_file][ input_data_files ..] 

옵션:
-n     결과행의 출력을 하지 않는다 
-e     편집할 명령을 기술한다. 각각의 편집 명령마다 이 옵션을 붙인다 
-f     편집할 명령을 파일로 작성한 뒤 파일에서 읽어서 명령을 실행한다 
input_data_file     입력을 지정하지 않으면 표준입력으로부터 입력을 읽어 들인다.

 

사용 형식 예제:

$ sed -e 'sed_command' -e 'sed_command' .... filenames 
$ sed -f sed_script_file filenames 
$ cat datafile 
Hello this is kim. 
I'm so happy to meet you. 
Test sample 
sample program 
Java programming

 

2) 라인 선택 출력과 파일로 출력

 

라인을 선택하여 출력할때는 -n 옵션과 sed명령중 p 명령을 이용하여 구현할 수 있다.

$ sed -n '1,3p' datafile <-- 1번-3번라인까지 출력한다. 
Hello this is kim. 
I'm so happy to meet you. 
Test sample 
$ sed -n '/^s/p' datafile 
sample program : 라인의 시작이 's'인 라인을 출력 
$ sed '/^s/p' datafile 
Hello this is kim. 
I'm so happy to meet you. 
Test sample 
sample program 
Java programming

$ sed -e '/^sample/w sam_file' datafile 
$ cat sam_file

sample program

 

3) 삭제, 추가, 삽입, 치환

 

삭제예
$ sed '1,3d 'datafile 
sample program 
Java programming 
$ sed '/^sample/,/^Java/d' datafile : 라인중 sample로 시작하는 라인 부터 Java로 시작하는 라인 까지 삭제
Hello this is kim.         
I'm so happy to meet you. 
Test sample

 

추가예
$ cat file1         : 각 라인의 아래에 '=====' 라인이 추가된다 

a\ 
===== 
$ sed -f file1 datafile 
Hello this is kim. 
===== 
I'm so happy to meet you. 
===== 
Test sample 
===== 
sample program 
===== 
Java programming 
=====

 

삽입예            : 각 라인 위에 '***' 라인이 추가된다
$ cat file2 
i\ 
*** 
$ sed -f sed_script_file filenames 
*** 
Hello this is kim. 
*** 
I'm so happy to meet you. 
*** 
Test sample 
*** 
sample program 
*** 
Java programming

 

치환예
$ sed -n '1,3s/t/T/gp' datafile         :변경된 라인만 출력 
Hello This is kim. 
I'm so happy To meet you. 
TesT sample 

$ sed '1,3s/t/T/g' datafile             :모든라인을 모두 출력 
Hello This is kim. 
I'm so happy To meet you. 
TesT sample sample program 
Java programming 

$ sed -n '1,3s/t/T/gw sam_file2' datafile     : 변경된 라인만 sam_file2 파일에 저장 한다 
$ cat sam_file2 
Hello this is kim. 
I'm so happy To meet you. 
TesT sample 

$ sed 's/\/export\/home/\home3/g']

'/' 문자는 '\'문자를 사용하여 표시한다. 
/export/home is user01's base directory <-- 입력라인 
/home3 is user01's base directory <- 출력라인

블로그 이미지

오픈이지 제로킴

시큐어코딩 교육/컨설팅 전문가 그룹

 2 부  쉘 프로그래밍


1장. 쉘 내장 명령들 

2장. 정규식과 유틸리티들 
3장. 쉘 프로그래밍 문법

 



1장.       쉘 내장 명령들


학습목표 : 쉘 내장 명령들을 이해하고 활용한다 

 


1. 쉘 내장 명령들



(1) export Command

 

Command: export [ name [ =value ] ] ...


Function: 지정된 names을 이후에 실행될 명령어의 환경에 자동적으로 넣기위해 사용한다.


Examples:

 

$ AA=100         // 현재 쉘에서 변수 AA에 100을 할당한다 
$ echo $AA     // 현재 쉘에서 변수 AA의 값을 출력한다 
100 
$ ksh             // 자식 쉘을 생성한다 
$ echo $AA
                    // 변수 AA의 값을 출력한다. 아무값도 출력하지 않는다

$ exit            // 다시 현재 쉘로 돌아 온다 
$ export AA   // AA 변수를 전역 변수로 설정한다 
$ ksh           // 자식 쉘을 생성한다 
$ echo $AA   // 변수 AA의 값을 출력한다 
100              // 변수 AA의 값을 출력한다



(2) readonly Command


Command: readonly [ name [ =value ] ] ...


Function: 지정하는 변수를 읽기 전용 변수로 설정하는 명령이다. 그 변수에 값을 배정하려고 시도한다면 쉘은 에러메세지를 출력한다. readonly변수는 사용자가 변수의 값을 너무 많이 쓰지 않도록 하는데 유용하다. 또한 쉘 프로그램을 사용하는 사람들이 특수변수(예를 들면 HOME 디렉토리나 PATH)의 값을 바꿀수 없도록 하는데도 유용하며 판독 전용의 성질이 서브쉘로 전달된다. 인수가 없는 readonly는 판독 전용 변수들의 리스트를 출력한다.

 

Examples:

 

$ DB=/usr/dgk/database 
$ readonly DB 
$ DB=foo 
DB: is read-only 
$ echo $DB 
/usr/dgk/database 



(3) unset Command

 

Command: unset [ -f ] name ...


Function: 각각 name에 대해서 해당하는 변수 또는 함수를 제거한다. 변수 PATH, PS1, PS2, MAILCHECK, IFS와 같은 환경변수에 대해 unset을 실행할 수 없다. 

Examples:

 

$ a=10 
$ set 
HOME=/home/kys 


TERM=vt100 
PS1=$ 
PS2=> 

a=10 
$ unset a 





(4) set Command

 

command: set -o korn_shell_mode


Function: 사용자 환경을 설정하는 명령이다


Options: korn_shell_mode


allexport        선언되는 모든 변수는 자동적으로 export 된다 
bgnice           우선권이 낮은 상태에서 백그라운드 작업 실행 
errexit            에러가 발생하면 exit가 실행된다 
ignoreoof       쉘을 종료하기 위해 반드시 exit명령을 실행한다 
markdirs         디렉토리명들은 / 로 표시된다 
noclobber       출력방향의 재지정시 기존 파일의 존재 여부를 체크하고난 뒤 실행하도록 지정 
noexec          명령어를 읽어 들이지만 실행 하지는 않는다 
nounset         변수값 치환시에 설정되어 있지 않은 변수는 오류로 취급한다 
trackall           실행하는 명령어들을 alias table에 등록한다 


(5) eval Command

 

Command: eval [ arg ... ]


Function: 쉘이 명령어 라인을 한번 해석한 후 대치와 확장을 끝내고 나서 명령어 라인을 한번 더 해석하도록할 때 사용한다. 

Examples:

 

$ x = 'abc def' 
$ y = '$x' 
$ echo $y 
$x 
$ eval echo $y 
abc def 





(6) exec Command

 

Command: exec [ command ] [ arg ... ]


Function: exec명령을 실행하면, 그 쉘이 지시된 인수들을 가진 지정된 명령을 실행한다. 보통 명령을 실행하면 쉘은 새로운 프로세스번호를 할당받아서 실행하지만 exec는 실행시키는 쉘의 프로세스번호를 지정한 명령에게 넘겨주므로 실행이 종료되면 명령어를 실행시켰던 쉘로 돌아가지 않는다.

 

Examples:

 

$ exec /usr/lbin/ksh         // Replace current process with ksh 

$ exec < datafile              // Reassign stndard input to datafile

$ exec 2> /tmp/errlog      // 표준에러출력전환 : 모든 에러출력은 /tmp/errlog로 
$ exec ls                         // ls를 수행하고 나면 logout 



(7) trap Command

 

Command: trap [ action ] [ condition ... ]


Function: 이 명령은 셀이 signals의 신호 중 하나를 수신할 때마다 명령을 실행하도록 한다. 인수가 없는 trap은 현재 설정되어 있는 trap 의 리스트를 출력한다.

 

$ trap "" signals 
signals에 있는 신호들을 수신하였을 때 그 신호는 무시된다.

 

$ trap signals 
signals에 리스트 된 각 신호들의 처리과정이 디폴트 동작으로 고정된다.

 

Examples:

 

  $ trap   // 모든 trap과 action 을 출력한다


  $ trap '$HOME/.logout' EXIT 
  // 쉘이 EXIT 신호를 수신하여 끝나게 되면 $HOME 디렉토리에

 

  $HOME 있는 .logout을 실행한다.


$ trap "echo hangup >> $ERRFILE; exit " 2 
//  interrupt 신호가 수신되면 hangup를 지정한 파일에 출력하고 현행 프로세스를 종료한다


$ trap "rm $TMPFILE; exit " 1 2 15


$ trap "" 2


$ trap INT QUIT TERM EXIT 
// INT QUIT TERM EXIT 의 trap을 unset한다. 각 신호의 디폴트 action으로 재설정한다


$ trap "echo $count line processed >> $LOGFILE; exit" 1 2 15 
// 1, 2, 15 신호중의 하나를 수신 받았을 때 count값을 $LOGFILE가 지정하는
   파일로 출력

 


 

trap을 위해 사용되는 신호번호 

 신호               내 용  

     HUP    hangup 
     INT    interrupt 
     QUIT   quit 
     ILL    불법 명령어 
     TRAP   추적 트랩 
     IOT    IOT명령 
     EMT    EMT명령 
     FPE    부동소숫점 예외 
     KILL   종료 
10     BUS    버스 에러 
11     SEGV   세그먼테이션 위반 
12     SYS    시스템 호출에 대한 불량 인수 
13     PIPE   기록한것이 없는 파이프상에서 판독 
14     ALRM   경보 클락 
15     TERM   종료(kill)로부터 소프트웨어 종료신호 
16     USR1   사용자 정의 신호1 
17     USR2   사용자 정의 신호2 
18     CLD    서브 쉘삭제

 

 

(8) echo Command

 

Command: echo [ arg ... ]


Function: 나열되는 아규먼트의 값들을 표준 출력으로 출력하는 명령이다. 이스케이프 문자를 사용하여 출력 특수 문자를 지정할 수 있다.

이스케이프 문자:

\a Bell 문자 
\b Backspace 
\c 종료개행 없는 라인 
\f 폼피드(formfeed) 
\n Newline 
\r Return 
\t Tab 
\\ Back-slash 
\nnn ACSII값이 nnn인 문자 
(nnn은 0으로부터 시작하는 0-3자리의 8진수임)

 

Examples:

   $ echo "test escape character \a\a\a\t hear me??\nThanks\n" 
   test escape character hear me? 
   Thanks 
   $

 

 

(9) print Command

 

Command: print [ -options [ n ] ] [ arg ... ]


Function: 아규먼트 리스트를 표준 출력응로 출력하는 명령이다. 

Options
      다음에 오는 모든 옵션들은 무시 
-n     라인의 끝에 개행문자를 두지 않음 
-r     echo의 이스케이프 시퀀스( \ ) 무시 
-R     -n 옵션외에 모든 옵션들을 무시 
-s     기록( history )화일에 args를 저장 
-un   화일 디스크립터 n에 출력 기록(디폴트 1) 
-p     |& 으로 생성된 프로세스에 출력을 기록

 

Ecamples:

 

$ print -r 'hi\\\\there' 
hi\\\\there 

$ print 'hi\\\\there' 
hi\\there 

$ print -s "vi echo.c" 
vi echo.c 



 

(10) read command

 

Command: read -options var1?prompt var2 . . .


Function: 쉘이 표준입력으로 부터 라인을 읽어 들이도록하는 명령이다. 라인에서 계속적으로 공백문자로 구분된 단어들을 변수 vars에 배정하고 라인의 단어보다 변수의 수가 적으면 마지막 변수에 초과한 단어들을 전부 저장한다.

?prompt가 지정되어 있으면 지정한 prompt가 데이타를 읽어 들이기위한 프롬트로 화면이 출력된다. 리스트된 변수명이 없는 경우 읽어들인 데이타는 쉘 내장 변수인 REPLY에 저장된다. 

 

Options:

-r     라인의 연속으로 끝에 붙어있는 \ 을 처리하지 않는다 
-s     기록화일(history)에 입력라인을 기록 
-un    화일디스크립터 n으로부터 데이타를 읽는다(디폴트 0) 
-p     |& 으로 생성된 프로세스 출력으로 읽어들인다.

 

Examples:

 

$ read hours mins 
10 19 
$ echo "$hours:$mins" 
10:19 
$ read file?"Which file: " 
Which file: edit.c 
$ echo $file 
edit.c 

$ read -r raw 
abc\ndef\t 
$ echo $raw 
abc\ndef\t 
$ read 
this is a test 

$ echo $REPLY 
this is a test 
$ cat read1 
while read -r 
do print -r "$REPLY" 
done <<! 
My Home directory is $HOME 





(11) ulimit Command

 

Command: ulimit [ -acdfmst ] [ n ]


Functions: 쉘에서 실행하는 프로세스에 최대 한계를 정하도록 한다.

 

Options
-a      모든 한계를 디스플레이한다. 
-c      코어 덤프를 n blocks으로 제한한다. 
-d      데이타의 크기를 n Kbytes로 제한한다. 
-f       차일드 프로세스에 의해 기록될수 있는 파일의 크기를 n blocks으로 제한한다. 
-m     프로세스나 차일드 프로세스가 사용할수 있는 물리적인 메모리 크기를 n Kbytes로 제한한다. 
-s      스택영역의 크기를 n Kbytes 로 제한한다. 
-t       각 프로세스가 사용할수 있는 시간을 n seconds로 제한한다.

 

Examples:

 

$ ulimit -f 1000 
$ ulimit -f 
1000

 




(12) umask Command

 

Command: umask [ mask ]


Function: 사용자 화일의 생성시 permission mode를 지정한다. 디렉토리 생성시에는 777(rwxrwxrwx) 에 대한 보수값& mask 을, 화일생성시에는 666(rw-rw-rw-)에 대한 보수값& mask을 permission mode 값으로 설정한다. mask값을 설정하지 않으면 현재 설정된 umask값을 출력한다.

 

Examples:

 

$ umask 022 # 디렉토리인 경우 755모드로 생성 , 화일인 경우 644모드로 생성 
$ umask 055 # 디렉토리인 경우 722모드로 생성 . 화일인 경우 622모드로 생성 
$ umask 
0055 
$

 

 



(13) '.' , ':' Command

 

Command: . filename


Function: 지정하는 filename 파일로부터 쉘 스크립트를 읽어서 현행 쉘에서 실행시킨다.

 

Command: :


Function: 필수적인 널 명령이다. : 명령은 명령이 나타내는 요구를 만족시키기 위해 자주 사용된다.

 

Examples:

 

if who | grep dgk > /dev/null 
then 

else 
    echo "dgk's not logged in" 
fi 





(14) let Command

 

Command: let arg ...


Function: let명령은 정수 연산 수식을 평가한다. 수식은 상수, 쉘변수, 그리고 연산자들을 포함할 수 있다. let은 let "expression" 또는 (( expression )) 의 형식으로 사용할 수 있다. 마지막 수식이 0값이 아니면 참, 0값이면 거짓이다. 수식안에 공백이 있으면 인용부호로 묶어서 사용한다. ( )를 이용하여 연산자의 우선 실행에 사용한다.

 

Examples:

 

$ cat let1 
let x=x+1 y=x%4+2 
integer n=${1-20} 
while (( (n=n-1) >= 0 )) && read -r line 
do 
print -r - "$line" 
done


$ cat let2 
let y=22*33 
let "z = y * y / (y -1)" "x = y + 1" 
if let "y % 12" 
then echo "y mod 12 != 0" 
else echo "y mod 12 == 0" 
fi


블로그 이미지

오픈이지 제로킴

시큐어코딩 교육/컨설팅 전문가 그룹

티스토리 툴바