본문 바로가기

IT/unix shell

KSH 스크립트의 기초

반응형

원문 : http://www.well.ox.ac.uk/~johnb/comp/unix/ksh.html

 

 

쉘타입의 정의

새로운 쉘스크립트를 만들때, 첫라인에 다음과 같이 써준다

다음:

 

#!/usr/bin/ksh

 

정확한 ksh 의 위치를 써주어야 하며, 32 character 를 넘어가면 안된다.

첫라인에 써주는 이정의로, 아래쪽의 모든스크립트는 ksh 가 처리하게 된다.

정의를 해주지않으면, 유저의 기본 쉘환경으로 지정된 쉘이 처리한다.

하지만 약간씩 다른 syntax 가 있기 떄문에 정확한 정의가 꼭 필요하다

 

4가지 종류의 행


스크립트는 4가지 종류의 라인정의가 있다:

최상단의 쉘정의 라인, 공란 라인, #으로 시작하는 주석 라인, 명령어라인.

아래의 예제를 보자:

 

#!/usr/bin/ksh

# Commentary......

file=/path/file
if [[ $file = $1 ]];then
   command
fi

 

스크립트의 시작과 끝스크립트는 처음 line 으로 시작해서, "exit" 문구를 만나거나, 마지막 라인까지 실행된다. 모든 "#"으로 시작하는 라인은 무시된다.

명령어의 시작과 끝명령어의 시작은 라인의 첫번째 단어또는, ";"로 구분된 후 처음단어로 시작할 수 있다.

명령어의 끝에는 ";" 를 쓰거나 쓰지 않을 수 있다.:

 

print -n "Name: "; read name; print ""

 

"\"를 이용하면, 라인이 넘어가는 명령어를 한라인 같이 연결하여 입력할 수 있다.

 

grep filename | sort -u | awk '{print $4}' | \
uniq -c >> /longpath/file


스크립트 파일의 이름과 권한스크립트는 다른 unix 명령어와 이름이 동일할 수 없다. :

그래서 "test" 같은 이름으로 정할 수 없다. ( 주: test 도 unix 명령어중 하나 )

스크립트 저장후, 실행을 위해서 실행권한이 필요하다. :

 

chmod 700 filename

 

--------------------------------------------------------------------------------변수

변수 값

 

 채우기변수값 채우는 방법은 이름을 이용하면 된다:

 

state="US"

 

숫자할당도 동일하다:

 

price=50

 

사용하기변수를 사용할때는 $ 기호를 변수앞에 붙여주면 된다:

 

print $state $price

 

배열변수 할당 및 사용하기:

 

arrname[1]=4 할당

print ${arraname[1]} 출력

${arrname[*]} 모든 배열 얻기

${#arrname[*]} 배열갯수 얻기

 

선언

 

ksh 에서는 변수를 선언한후 쓸필요는 없다. One cannot have decimals only integers. ( 주. 잘모르겠음요;; )

 

--------------------------------------------------------------------------------분기문

 

if then fi

 

if [[ $value -eq 7 ]];then
   print "$value is 7"
fi

 

또는:

 

if [[ $value -eq 7 ]]
then
   print "$value is 7"
fi

 

또는:

 

if [[ $value -eq 7 ]];then print "$value is 7";fi

if then else fi

 

if [[ $name = "John" ]];then
   print "Your welcome, ${name}."
else
   print "Good bye, ${name}!"
fi


if then elif then else fiif [[ $name = "John" ]];then
   print "Your welcome, ${name}."
elif [[ $name = "Hanna" ]];then
   print "Hello, ${name}, who are you?"
else
   print "Good bye, ${name}!"
fi


case esac

 

case $var in
   john|fred) print $invitation;;
   martin)    print $declination;;
   *)         print "Wrong name...";;
esac


추가 테스트(주.)

 

name="HanTaeJong";

if [ $name = "anTaeJong" ]
then
    print "then Name: $name";
else
    print "else Name: ${name}";
fi

 

print $name;:: if 조건문 [] 하나만 써도 됨:: $name , ${name} 차이 없음

 

--------------------------------------------------------------------------------반복문

 

while do done

 

while [[ $count -gt 0 ]];do
   print "\$count is $count"
   (( count -= 1 ))
done


until do done

 

until [[ $answer = "yes" ]];do
   print -n "Please enter \"yes\": "
   read answer
   print ""
done


for var in list do done

 

for foo in $(ls);do
   if [[ -d $foo ]];then
      print "$foo is a directory"
   else
      print "$foo is not a directory"
   fi
done


continue...break

 

해당반복을 스킵하고 다음반복을 진행하고 싶은경우:

"continue".

 

while read line
do
   if [[ $line = *.gz ]];then
      continue
   else
      print $line
   fi
done


루프문종료를 원할경우:

 "break".

 

while read line;do
   if [[ $line = *!(.c) ]];then
      break
   else
      print $line
   fi
done

 

--------------------------------------------------------------------------------명령행 인수

 

(공식적으로는  "positional parameters" 라고 한다)

명령행 인수의 갯수는  $# 에 저장되어 있다. 그러므로,명령행 인수가 들어왔는지 여부를위해:

 

if [[ $# -eq 0 ]];then
   print "No Arguments"
   exit
fi


각각의 인수는  $1, ....$n 순서대로 저장되어있으며, $* 에 모든 인수가 저장되어 있다.

인수는 수정될 수 없지만, 추가는 가능하다.

만약 첫번째 인수로  $first 변수를 삽입하는 경우:

 

if [[ $1 != $first ]];then
   set $first $*
fi


shift 커맨드를 이용하여, 인수의 제거도 가능함. 첫번째 인수부터 하나씩 제거됨

 

until [[ $# -eq 0 ]];do
   # commands ....
   shift
done


for 반복문을 이용하여, 인수의 활용도 가능하다. (기본변수 arg ) $*:

 

for arg;do
   print $arg
done


프로그래명은  $0 에 저장되나, 경로까지 같이 저장됨!

 

--------------------------------------------------------------------------------비교기호

 

문자비교인 경우 같다는  "="  같지않다 "!=" 를 사용한다.

숫자비교인 경우  같다 "-eq"  같지않다 "-ne" 크다 "-gt" 작다 "-lt"  를 사용한다.

 

if [[ $name = "John" ]];then
   # commands....
fi


if [[ $size -eq 1000 ]];then
   # commands....
fi


조건문의 연결로 그리고  "&&"  또는  "||" 의미로 사용할 수 있다.

 

if [[ $price -lt 1000 || $name = "Hanna" ]];then
   # commands....
fi


if [[ $name = "Fred" && $city = "Denver" ]];then

 

--------------------------------------------------------------------------------변수 변경하기

 

변수에서 필요없는 부분의 제거변수에 포함되어 있는 경로부분을 제거할때 이용:

 

${name##*/}

파일명만 남기고 나머지를 삭제해줌

 

경로만 남기고 싶을때:

 

${name%/*}

 

 % 왼쪽부분을 취할때 # 오른쪽부분을 취할때%% , ##  가장긴 부분  % ,# 가장 짧은 부분

 

할당되지 않은 변수에 대하여 임시변수 할당

 

$foo 라는 변수에 변수가 아직 할당되지 않았을 경우 할당하고 싶을때:

 

${foo:-4}

 

 하지만 이렇게 하더라도 아직 변수는 할당되지 않은채로 있음.

할당되는걸로 바꾸고 싶은 경우:

 

${foo:=4}

 

(주. 예제가 필요해서 추가 함)

 

#foo=1;

print ${foo:-4};

print $foo;

print ${fpp:=4};

print $foo;

 

#주석처리된 foo=1; 을 주석제거 하고 안하고를 비교해보면 잘 알수 있음

 

변수가 할당되지 않았을 경우의 활용

 

해당변수가 할당되지 않을 경우 해당문구 출력(해당라인에서 실행중단):

 

 ${foo:?"foo not set!"}

 

변수 체크

 

${foo:+1}

 

변수가 할당된 상태면 1을 할당함,

그렇지 않을경우 할당하지 않음

--------------------------------------------------------------------------------Ksh 정규표현식

 

Ksh 는 자신만의 정규표현식을 갖는다. * 는 모든 문자를 뜻한다. 그러므로 .c 로 끝나는 모든 문자는 *.c 를

사용하면 된다.? 는 문자개를 뜻한다.:

 

?44.f.ksh 에서 패턴의 수를 정하는 한정자이다.:

 

?(pattern) 0,1 번 패턴.

*(pattern) 0번이상 패턴.

+(pattern) 1번이상 패턴.

@(pattern) 1번 패턴.

!(pattern) 괄호안의 문자그대로 패턴.

 

다음은 어떤문자와 매치될런지 생각해보자:

if [[ $var = fo@(?4*67).c ]];then ...

 

--------------------------------------------------------------------------------함수설명

 

함수( 프로시져)는 반드시 호출전에 정의되어 있어야한다.

왜냐하면, ksh 는 인터프리터 이기 때문에 함수 호출시 명령행 인수를 제외한 모든게 선언이 되어 있어야 하기 때문이다.

함수 정의둘중에 하나의 방법으로 정의 할 수 있다:

 

function foo {
   # commands...
}

 

foo(){
   # commands...
}
함수호출스크립트에 함수명을 쓰므로써 호출이 가능하다: foo. 인수를 주는방법은 다음과 같다:

 

foo arg1 arg2 ...

 

인수는 명령행과 동일하게  $1...$n 로 처리하며 $* 로 모든인수를 볼수 있다.

메인의 $1 는 함수내의  $1 에 영향을 받지 않는다.

Return return 명령어는 즉시 함수를 종료한다.

(주. return 시에 return 값을 줄수 없는거 같은데 맞는지 모르겠음 ㄷㄷㄷ )

 

--------------------------------------------------------------------------------데이터 리다이렉션

 

일반데이터의 리다이렉션은 다음과 같이 쓸수 있다: "> >> < <<".

모든 프로그램은 적어도 표준입력, 표준출력 그리고 표준오류출력을 갖는다.

이 세가지 모두 리다이렉션이 가능하다..

프로그램 실행후 결과값 파일로 저장하기결과파일을 생성하거나 덮어써서 기록하기:

 

command > file

 

기존파일에 이어쓰기:

 

command >> file

 

표준에러출력의 리다이렉션표준 에러출력을 리다이렉션 하기:

 

command 2> file

 

표준 에러출력을 버리기:

 

command 2>/dev/null

 

표준 에러출력을 표춘출력으로 전환 :

 

command 2>&1

 

프로그램에 파일 넣기프로그램이 표준입력을 받는다면 파일을 표준입력으로 입력 가능:

 

command < file

 

입력 출력 리다이렉션 결합

 

command < infile > outfile

command < infile > outfile 2>/dev/null

 

Commands into Program  ( 주. 머라고 해야할지;; )

 

모든 유닉스 커맨드는 텍스트 리스트를 받을수 있다:

 

command <<EOF

input1

input2

input3

EOF

 

command 에 EOF ~ EOF 사이의 input 이 들어간다.

--------------------------------------------------------------------------------파이프

 

일련의 결과들이 다음커맨드로 이어져서 실행된다:

 

command1 | command2 | command3 ...

 

e.g. last | awk '{print $1}' | sort -u.

 

--------------------------------------------------------------------------------협업처리

 

One can have one background process with which one can comunicate with read -p and print -p. It is started with command |&. If one uses: ksh |& then this shell in the background will do everything for us even telnet and so on:

 

print -p "telnet hostname".

 

------------------------------------------------------------------사용자 또는 파일로부터 읽어들이기

 

변수에서 읽기유저로부터 입력을 받을때, newline 의 무시를 위해 -n 옵션을 이용한다.:

 

print -n "Enter your favorite haircolor: ";read var; print ""

 

파일에서 라인을 읽고 저장하기파일에서 반복적으로 읽기:

 

{ while read myline;do
   # process $myline
done } < filename


파이프라인을 이용하여 결과의 마지막을 읽기:

 

last | sort | {
while read myline;do
   # commands
done }


--------------------------------------------------------------------------------특별한 변수들

 

$# 명령행의 인수 수.

$? 마지막 명령어의 종료상태.

$$ 실행중인 프로그램의 ID.

$! 마지막으로 실행한 백그라운드 잡 또는 함수의 ID

$0 프로그램의 이름 path 포함, 다른 디렉토리에서 실행했어도 포함함.

$1..n 명령행 인수

$* 모든 명령행 인수 1개의 문자열.

 

--------------------------------------------------------------------------------명령어의 성공과 실패첫번째 명령어가 실행되었을때만 연결해서 실행하기:

command1 && command2.

 

첫번째 명령어가 실패하면 두번째 명령어 실행하기:

command1 || command2.

 

--------------------------------------------------------------------------------간단한 계산

 

간단한 계산식은 let 을 쓰거나  (( ... )) 안에 써서 실행이 가능함.

"$"을 쓰지 않는다.

 

1씩 증가하는 간단한 식:

(( a+=1 )) or let a+=1.

 

(주. 아래부터는 생략함 )!

 

--------------------------------------------------------------------------------Numerical Calculations using "bc"For bigger caluculations one uses "bc" like:

$result=$(print "n=1;for(i=1;i<8;i++)n=i*n;n"|bc)

 

--------------------------------------------------------------------------------"grep"

 

Search for the occurence of a pattern in a file: grep 'pattern' file. If one just wants to know how often soemthing occurs in a file, then: grep -c 'pattern file. This can be used in a script like:if [[ $(grep -c 'pattern' file) != 0 ]];then ......;fi. The condition is fullfilled if the pattern was found.

 

--------------------------------------------------------------------------------"sed"

 

Sed means stream line editor. It searches like grep, but is then able to replace the found pattern. If you want to change all occurences of "poor" with "rich", do:sed -e 's/poor/rich/g' filename. Or what is often seen in software packages, that have to be compiled after getting a propper configuration, is a whole file stuffed with replacements patterns like: /@foo@/s;;king;g. This file with inumerable lines like that has to be given to sed with: sed -f sedscript filename. It then precesses each line from file with all the sed commands in the sedscript. (Of course sed can do much more:-))

 

--------------------------------------------------------------------------------"awk"

 

Awk can find and process a found line with several tools: It can branch, loop, read from files and also print out to files or to the screen, and it can do arithmetics.For example: We have a file with lines like: Fred 300 45 70 but hundreds of them. But some lines have a "#" as the first sign of them and we have to omit these ones for both, processing and output. And we want to have lines as output like: 415 Fred where 415 is the sum of 300, 45 and 70. Then we call on awk:awk '$1 !~ /^#/ && $0 ~ /[^ ]/ {print $2+$3+$4,"\t",$1}' filename.This ignores lines with a "#" at the beginning of the first field and also blank lines. It then prints the desired sum and the $1 ist only printed after a tab. This is the most trivial use of awk only.Check my AWK programming introduction bye clicking on this sentence!

 

--------------------------------------------------------------------------------"perl"

 

Perl is a much richer programming language then ksh, but still one can do perl commands from within a ksh script. This might touch Randal, but it's true. Let's say you want to remove all ^M from a file, then take perl for one line in your ksh script:perl -i -ep 's/\015//g' filename.Perl can do an infinite amount of things in many different ways. For anything bigger use perl instead of a shell script.Check my PERL programming introduction bye clicking on this sentence!

반응형