C Shell은 산술 연산, 문자열 비교, bit 연산 그리고 논리연산을 할 수 있다. C Shell의 연산자도 C언어와 동일한 문법과 연산 우선 순위를 갖는다.
C Shell의 약점은 이 연산 부분이다. C Shell은 내부에서 변수 값을 string으로 저장하고 연산 시에 숫자로 변환하는 과정을 거치기 때문에 연산은 많은 시간을 필요로 한다. 만일 연산을 많이 하는 과정을 Shell과 같은 script 언어로 작성하고 싶다면 awk나 perl의 사용을 권한다. 또한 C Shell에서는 실수 연산을 할 수 없다.
3.4.1 연산자의 사용
사용방법은 산술연산을 시작하는 기호인 @ 뒤에 수행하고자 하는 산술식을 입력한다. 다음은 산술연산의 사용 방법과 사용 시 주의점에 대한 것이다.
사용 방법 :
@ variable_name operator expression
1. @와 variable_name 사이에는 반드시 "공백"을 넣어야 한다.
2. variable_name은 c shell 변수이고 expression은 수식이다.
3.4.2 Assignment Operator
C Shell에서 다음과 같이 연산을 수행한다.
1. @ 연산자를 사용하여 사칙연산을 할 수 있다.
2. =,+,-,+=,-=,*=,/= 의 앞 뒤에는 반드시 공백이 있어야 한다.
3. 나눗셈 연산은 몫이나, 나머지를 지정하여 연산한다.
4. 변수 이름과 ++ 또는 -- 사이에는 공백이 있어서는 않된다.
5. @ variable_name[index] = expression 과 같이 목록 변수를 사용할 수 있다
6. @ 연산자를 문자열 데이터와 함께 사용할 수 없다.
예 제 1 :
% @ count = 6 일 때
Symbol |
Meaning |
Sample |
%echo $count |
= |
변수에 우변 값을 저장한다. |
@ count = 3 |
3 |
+= |
변수에 우변 값을 더한다. |
@ count += 6 |
9 |
-= |
변수에 우변 값을 뺀다. |
@ count -= 5 |
4 |
*= |
변수에 우변 값을 곱한다. |
@ count *= 8 |
32 |
/= |
변수에 우변 값으로 나눈 몫 |
@ count /= 5 |
6 |
%= |
변수에 우변 값으로 나눈 나머지 |
@ count %= 4 |
2 |
++ |
변수에 1 을 더한다. |
@ count++ |
3 |
-- |
변수에 1을 뺀다. |
@ count-- |
2 |
Sample 난에 있는 연산을 수행 후 그 결과는 “echo $count”와 같이 하면 알 수 있다.
예 제 2 :
% @ num = 20 일 때
Symbol |
Meaning |
Sample |
%echo $r |
+ |
덧셈 |
@ r = $num + 6 |
26 |
- |
뺄셈 |
@ r = $num - 3 |
17 |
* |
곱셈 |
@ r = $num * 5 |
100 |
/ |
정수 나눗셈(몫 계산) |
@ r = $num / 6 |
3 |
% |
정수 나뭇셈(나머지 계산) |
@ r = $num % 6 |
2 |
3.4.3 Bitwise and Logical Operators
C Shell에서는 bit 연산과 논리 연산을 지원한다.
1. bit 연산에서 빈자리는 "0"으로 채워진다.
2. >>, <<, &, |, ^ 연산자를 포함하는 식은 반드시 괄호로 묶어야 한다.
3. 연산자가 아닌 입출력 재지정, 후위 작업, 파이프 등의 부호로 인식될 수 있기 때문이다.
사용 방법 :
Bitwise shift operator : >> (shift right), << (shift left)
Bitwise unary operator : ~ (1's complement), ! (logic negation)
Bitwise logic operator : | (OR), ^ (XOR), & (AND)
Logical operator : || (logic OR), && (logic AND)
예 제 1 :
% @ aa = 20
% @ bb = (~ $aa)
% echo $bb
-21
% @ aa = 25
% @ bb = (! $aa)
% echo $bb
0
% @ bb = (! (! $aa))
% echo $bb
1
예 제 2 :
% @ aa = 5
% @ bb = ($aa << 1)
% echo $bb
% @ bb = ($aa << 4)
% echo $bb
(참고) 4의 배수로 계속 실행을 해보라 어떤 결과를 얻을 수 있는가 ?
3.4.4 Comparison Operators
C Shell에는 숫자, 문자열, pattern의 세 가지 형태의 자료에 대한 비교 연산자가 있다. 각각의 연산자는 다음과 같다.
1. 숫자 비교 연산자 : ==, !=, >, >=, <, <=
2. 문자열 비교 연산자 : ==, !=
3. Pattern matching 연산자 : =~, !~
4. Pattern matching의 meta character는 파일이름 확장에 사용된 것과 동일하다.
* : Match any string(including null)
[ ] : Define a character set
? : Match a single character
예 제 :
Symbol |
Meaning |
Sample |
Result |
== |
equal to |
$num == 5 |
True (@num = 5) |
!= |
not equal to |
$num != 5 |
False |
> |
grater than |
$num > 3 |
True |
>= |
grater than or equal to |
$num >=3 |
True |
< |
less than |
$num < 3 |
False |
<= |
less than or equal to |
$num <=3 |
False |
== |
equal to |
$str == xyz |
True ($str = xyz 일때) |
!= |
not equal to |
$str != abc |
True($str = xyz 일때) |
=~ |
matches |
$pat =~ [abc]* |
True ($pat이 abc로 시작) |
!~ |
does not match |
$pat !~ *c |
False ($pat이 c로 종료) |
if 구문을 사용한 조건부 실행은 프로그램의 작성에 가장 많이 사용하는 기능으로, 어떤 조건을 만족할 경우, 특정 명령어나 작업을 실행하고자 할 때 사용한다.
3.5.1 if 구문
If 구문의 사용은 if ~ endif 로 끝나는 간단한 구문에서 if ~ else if ~ else if … endif로 끝나는 복잡한 구문까지 사용할 수 있다. 그리고 if 구문 안에서 또 if 구문을 사용하는 계층 구조도 사용할 수 있다.
사용 방법 :
1. if (expression) command
2. if (expression) then
command(s)
endif
3. if (expression) then
command(s)
else
command(s)
endif
4. if (expression) then
command(s)
else if (expression) then
command(s)
. . .
else
command(s)
endif
5. expression에는 comparison operator를 사용한다.
예 제 1 :
1. editor를 사용하여 host_check 파일에 다음의 내용을 입력한다.
< host_check >
#!/bin/csh -f
set ps = “/usr/ps ?elfo s,user,pcpu,pmen,args”
set testhost = $argv[1]
set testload = `rup $testhost | cut -c53-56`
if ($status == 0) then
echo $testhost
rsh $testhost $ps | grep “^O “ | egrep -v ‘(csh|aux|grep)’
else
echo “$testhost down”
endif
2. 파일을 실행할 수 있도록 mode를 변경한다.
% chmod 755 host_check
3. 파일을 실행한다,
% host_check test_hostname
% host_check borisu
4. 이 프로그램의 실행 결과는 testhost가 동작되고 있으면 현재 실행중인 작업을 보여주고, 시스템이 반응하지 않으면 “testhost down”이라는 메시지를 보여준다.
5. rup으로 시스템을 check하는데 문제가 있으면 이 부분을 다음과 같이 수정하면 많은 문제가 없어진다.
rup $testhost | cut ?c50- | awk ‘{print $2}’ | tr ?d ‘.’
3.5.2 File Inquiry Operator
C Shell에서는 파일의 존재 유무나 특성을 Check 할 수 있는 기능을 제공한다. 이 기능과 if 구문을 조합하여 다양한 기능을 하는 프로그램을 작성할 수 있다.
사용 방법
if ( -operator filename ) ...
각 Operator의 의미는 다음과 같다.
논리 부정을 사용할 때는 연산자 ! 를 앞의 operator와 함께 사용한다.
if (! -e file_name) then
예 제 :
<file_check >
#!/bin/csh -f
set testfile = $1
if (! ?e $testfile) then
echo “$testfile is not exist”
exit
endif
if (-z $testfile) then
echo “$testfile is blank file”
else if (-f $testfile) then
@ mode = 0
if (-r $testfile) @ mode += 4
if (-w $testfile) @ mode += 2
if (-x $testfile) @ mode += 1
if ($mode == 7) echo “$testfile mode is Read, Write, Execute”
if ($mode == 6) echo “$testfile mode is Read, Write”
if ($mode == 4) echo “$testfile mode is Read Only”
else if (-d $testfile) then
echo $testfile is directory
else
echo "$testfile is not plan_file and directory"
echo "$testfile is special file"
endif
# End of File
일정 횟수로 어떤 구문을 반복 실행하고자 할 때 foreach ~ end 구문을 사용한다. foreach 구문에서 반복 횟수는 변수 list의 개수와 같다. 반면에 while 구문(다음에 설명)은 조건이 만족하는 한 while ~ end 사이의 구문을 반복한다.
사용 방법 :
foreach name ( wordlist )
command(s)
. . .
end
1. 반복 실행할 때 마다 wordlist에 있는 다음 단어를 name에 할당한다.
2. end는 foreach 반복 문의 끝을 나타낸다.
3. foreach 구문의 실행중 빠져 나오려면 break를 사용한다.
(Break 는 foreach, while 등의 구문의 실행 중 중간에서 이 구문을 벗어나고자 할 때 사용한다.)
4. wordlist 는 변수들의 리스트나 집합 변수를 사용한다.
예 제 1 :
다음의 프로그램은 argument로 여러 대의 hostname을 입력 받아 각 시스템에서 현재 CPU에서 실행(State 필드가 O(On CPU)나 R(Runnable)인 프로세스)되고 있는 작업을 보여준다.
< host_check >
#!/bin/csh -f
set ps = “/usr/ps -elfo s,user,pcpu,pmen,args”
foreach testhost ($argv)
set testload = `rup $testhost | cut -c50- | awk ‘{print $2}’ | tr -d‘.’`
if ($status == 0) then
echo $testhost
rsh $testhost $ps | egrep ‘(^O | ^R)’ | egrep -v ‘(csh|aux|grep)’
else
echo “$testhost down”
endif
end
# End of file
예 제 2 :
다음의 프로그램은 argument로 입력된 디렉토리나 현재 디렉토리(argumenet가 없을때)에 포함된 파일의 개수와 디렉토리 개수를 세어 그 결과를 보여준다.
< file_count >
#!/bin/csh -f
# Counts number of files and directoris in argument1
# or current directory
# Usage : numfile [directory]
if ($#argv == 0) then
set dir = "."
else
set dir = $argv[1]
endif
if (! -d $dir) then
echo $0\: $dir not a directory
exit 1
endif
echo $dir\:
@ fcount = 0
@ dcount = 0
cd $dir
foreach file (*)
if (-f $file) then
@ fcount++
else if (-d $file) then
@ dcount++
endif
end
echo $fcount files $dcount directories
# End of file
(주의) 위의 예제에서 foreach file (*)에서 (*)의 의미는 현재 디렉토리에 포함된 파일과 디렉토리의 리스트를 의미한다. foreach file (`ls`)로 실행하여도 되나 ls를 사용하면 ls 실행을 위한 sub shell이 만들고 그 결과를 받아 수행하므로 속도가 늦다. (*)는 sub shell을 만들지 않고 바로 실행하므로 속도가 빠르고 시스템의 자원도 적게 사용하게 된다.