2009년 3월 1일 일요일

3Day Study

3Day Study
쉘 스크립트 내장 명령어
break; <= 중간에 빠저나올때 사용
: <= 널 명령 or true(예: while : 와 while true와 같다)
: ${var:=value} <= :이 없으면 쉘은 $var을 명령으로 연산하고자 시도한다
continue <= 반복문에서 사용
for x in 1 2 3
do
echo before $x
continue 1
echo after $x
done

결과값
before 1
before 2
before 3

. <= 현재 쉘에서 명령 실행(예: . ./shell_script) C에서 #include 지시어와 약간 비슷
파일명 classic_set
#!/bin/sh
version=classic
PATH=/usr/local/old_bin:/usr/bin:/bin:.
PS1="calssic> "
파일명 lastst_set
#!/bin/sh
version=latest
PATH=/usr/local/new_bin:/usr/bin:/bin:.
PS1=" latest version> "

결과는
# . ./calssic_set
calssic> echo $version
classic
classic> . latest_set
latest version> echo $version
latest
latest version>

echo <= 문자열과 줄 바꿈 문자를 출력하기 위해서 사용(이식성을 위해서는 tr 명령을 이용
echo -n "string to output"
echo -e "string to output\c" <= \t(탭), \n(캐리지 리턴)

eval <= 인자를 연산할 때
foo=10
x=foo
y='$' $x
echo $y

결과값
foo

foo=10
x=foo
eval y='$' $x
echo $y

결과값
10

exec <= 다른 프로그램을 실행 및 현재 파일 설명자를 수정
exec wall "Thanks for all the fish"
exec 3< afile <=이것은 파일 asfile로 부터 읽기 위해 설명자 3을 사용하여 연다

exit <= 스크립트 종료 기능
exit 0 <= 성공 종료(에러코드는 1~125 까지 존재함)
125 <= 파일이 실행 가능이 아니다
127 <= 명령을 찾을 수 없다
128이상 값 <= 신호(signal)가 발생하였다

AND OR 응용
#!/bin/sh
if [ -f .file ]; then
exit 0
fi
exit 1

[ -f .profile] && exit 0 || exit 1
는 같다

export <= 매개변수로 받은 이름의 변수를 하위 쉘에서 사용 가능하도록 만들어줌
파일명 export2
#!/bin/sh
echo "$foo"
echo "$bar"
파일명 export1
foo="foo"
export bar="bar"
export2

결과값은
$ export1

bar
set -a 또는 set -allexport <= 모든 변수를 내보낸다

expr <= 자신의 인자를 표현식으로 연산
x=`expr $x + 1`
x=$(expr $x + 1)
요즘은 expr 보단 $((수식)) 이 쓰임(expr 보다 빠르다)
x=$((3+1))

printf <= 화면출력하기(echo 보다 좋지만 최신의 쉘에서 사용 가능, 소수점은 지원안됨)
\\ <= 백슬래시 문자
\a <= 벨 울리기
\b <= 백스페이스 문자
\f <= 폼 피드 문자
\n <= 줄 바꿈 문자
\r <= 캐리지 리턴
\t <= 탭 문자
\v <= 수평 탭 문자
\ooo <= 8진수 값 ooo을 가진 단일 문자
%d <= 십진수를 출력
%c <= 문자를 출력
%s <= 문자열을 출력

$ printf "%s %d\t%s" "Hi There" 15 people
Hi Theere 15 people

return <= 기본적으로 마지막 명령의 종료 코드 반환

set <= 매개변수을 설정할 때
#!/bin/sh
echo the date is $(date)
set $(date)
echo The month is $2
exit 0

결과는(set으로 매개변수를 설정 후 $2를 사용해서 달(Month)를 갖고온다)
the date is Mon Mar 2 11:46:12 KST 2009
The month is Mar

set -x <= 스크립트가 현재 실행 명령들의 추적을 표시함

shift <= 매개변수를 하나씩 아래로 옮긴다($2->$1, $0은 변하지 않음, $* $@ $# 매개변수들이 새로운 정렬에 따라 값이 변하게 됨)

모든 매개변수 검사
#!/bin/sh
while [ "$1" != "" ]; do
echo "$1"
shift
done
exit 0

trap -l <= SIG 신호들 보기(신호를 이용해서 작동을 지정)
trap 중요한 신호들
HUP(1) <= 행업(대개 터미널을 끊고 사용자가 로그아웃할 때 전송)
INT(2) <= 인터럽트(대개 Ctrl+C를 눌러서 전송)
QUIT(3) <= 끝내기(대개 Ctrl+\를 눌러서 전송)
ABRT(6) <= 중단(대개 어떤 심각한 실행 에러일 때 전송)
ALRM(14) <= 알람(대개 시간 제한을 처리할 때 사용)
TERM(15) <= 종료(대개 시스템이 종료할 때 전송)

#!/bin/sh
trap 'rm -f /tmp/my_tmp_file_$$' INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo "press interrupt (CTRL-C) to interrupt ...."
while [ -f /tmp/my_tmp_file_$$ ]; do
echo File exists
sleep 1
done
echo The file no longer exists
trap INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo "press interrupt (control-C) to interrupt ...."
while [ -f /tmp/my_tmp_file_$$ ]; do
echo File exists
sleep 1
done
echo we never get here
exit 0

결과는(처음 while 까지 실행 후 Ctrl+C를 누르면 두번째 while문 진입 후 Ctrl+C를 누르면 바로 종료가 되서 echo we never get here 밑으로는 실행되지 않음) <= 잘 안됨
creating file /tmp/my_tmp_file_141
press interrupt (CTRL-C) to interrupt ....
File exists
File exists
The file no longer exists
creating file /tmp/my_tmp_file_141
press interrupt (CTRL-C) to interrupt ....
File exists
File exists

unset <= 변수나 함수를 환경에서부터 메모리에서 완전 삭제함(IFS 같은 읽기 전용 변수는 사용이 안됨)
#!/bin/sh
foo="Hello World"
echo $foo
unset foo
echo $foo

결과(foo=과 틀림 foo가 완전히 사라짐)
Hello World

유용한 명령어들
파일 찾기
find [경로] [옵션] [테스트] [작동]
fine / -mount -name wish -print <= wish파일을 찾는데 마운트된 시스템은 안 찾음
-depth <= 디렉토리의 내용을 먼저 검색
-follow <= 기호화된 링크를 따라감
-maxdepths N <= 검색할때 최대 N 수준까지의 디렉토리를 검색
-mount <= 다른 파일 시스템의 디렉토리는 검색하지 않음
-atime N <= 파일이 N일 이전에 마지막으로 액세스 되었다
-mtime N <= 파일이 N일 이전에 마지막으로 수정되었다
-name "패턴" <= 경로를 제외한 파일의 이름이 주어진 패턴에 일치
-newer otherfile <= 파일이 otherfile보다 최신이다
-type C <= 파일 형식이 C, d는 디렉토리, f는 보통 파일
-user 사용자이름 <= 주어진 이름을 가진 사용자가 파일을 소유하고 있다
! or -not <= 테스트를 역으로 수행
-a or -and <= 두 테스트가 모두 true
-o or -or <= 둘 중 하나의 테스트가 true

파일 X보다 최신이거나 밑줄로 시작하는 이름의 보통파일만 찾아서 출력
find / \( -newer X -or -name "_*"\ ) -type f -print <= (는 특별한 의미기 때문에 \ 필요
find 작동후 수행 옵션은
-exec 명령 <= 명령을 실행
-ok 명령 <= -exec와 같지만 실행하기 전에 사용자에게 여부를 물음
위 두가지는 \;로 끝냄 {}은 현재 파일에 대한 전체 경로로 인식
-print <= 파일의 이름을 출력
-ls <= 현재 파일에 대해서 ls -dils 명령을 사용
파일 X보다 최신이거나 밑줄로 시작하는 이름의 보통파일만 찾아서 ls -l 하기
find / \( -newer X -or -name "_*"\ ) -type f -exec ls -l {} \;
결과는
-rwxr-xr-x 1 root root 5984 Mar 15 2007 /usr/lib/python2.4/site-packages/rhpl/_diskutil.so

find / \( -newer X -or -name "_*"\ ) -type f -exec ls -l \;
결과는
-rwxr-xr-x 1 root root 75 Mar 2 11:46 setsample.sh

grep <= 일반 정규식 파서
grep [옵션] 패턴 [파일]
-c <= 일치하는 줄의 갯수 출력
-E <= 확장 표현식을 적용
-h <= 파일명 붙이는거 제거(일반적으로 grep는 찾은 패턴의 앞에 파일명이 나옴)
-i <= 대소문자를 구별 안함
-l <= 일치된 줄에 해당하는 파일 이름만 나열
-v <= 일치된 패턴 제거

grep -c -v in words.txt <= words.txt안에 in 문자가 없는 줄의 갯수 파악

많이 쓰이는 정규표현식(상세한 정규표현식은 info grep에서 Regular Expressions 부분 보기)
^ <= 문자의 시작
$ <= 문자의 끝
. <= 어떤 단일 문자
? <= 필수가 아니여도 1번 일치
* <= 0번 혹은 더 많이 일치
+ <= 1번 혹은 더 많이 일치
{n} <= n번 일치
{n,} <= n번이상 일치
{n,m} <= n번에서 m번 사이에 일치
[ ] <= 일치되는 문자의 범위(예: ^[a-e]는 a에서 e까지의 역이다)

grep e$ words.txt <= e로 끝나는 문자 찾기
grep a[[:blank:]] words.txt <= a로 끝나는 단어 찾기([[:blank:]]는 공백이나 탭)
grep Th. [[:space:]] word.txt <= Th로 시작되는 단어 찾기
grep -E [a-z]\{10\} word.txt <= 소문자가 10자로 단어 찾기

!!중요 포인트!!
명령 실행의 오래된 형식에서는 작은 따옴표가 아니라 백틱 혹은 백따옴표)`_를 사용하였음을 명심하자
$(명령}은 단순히 명령의 출력임

!!중요 포인트!!
1_tmp와 2_tmp 제어할때
#!/bin/sh
for i in 1 2
do
my_secret_rpocess $i_tmp
done

결과는(에러가 남)
my_secret_process: too few arguments
에러 수정 방법
my_secret_rpocess $i_tmp => my_secret_rpocess ${i}_tmp

매개변수 확장
${param:-default} <= param이 널이면 default의 값으로 설정
${param:=default} <= param이 널이 아니면 변수의 값을 반환하며, 그렇지 않으면 foo를 bar로 설정하고 이 값을 대신 반환
${param:?default} <= param: default를 출력하고, param이 존재하지 않거나 널이면 명령 중지
${param:+default} <= param이 존재하고 널이 아니면 default를 반환
${#param} <= param의 길이를 준다
${param%word} <= 끝에서부터 word에 일치하는 param의 가장 짧은 부분을 제거하고 나머지 반환
${param%%word} <= 끝에서부터 workd에 일치하는 param의 가장 긴 부분을 제거하고 나머지를 반환
${param#word} <= 처음부터 word에 일치하는 param의 가장 짮은 부분을 제거하고 나머지를 반환
${param##word} <= 처음부터 word에 일치하는 가장 긴 부분을 제거하고 나머지를 반환

#!/bin/sh
unset foo <= foo 메모리 삭제
echo ${foo:-bar} <= 기본으로 foo에 bar 넣고 출력
foo=fud <= foo에 fud 넣기
echo ${foo:-bar} <= foo에 fud가 있기 때문에 fud 출력
foo=/usr/bin/X11/startx <= foo에 /usr/bin/X11/startx 입력
echo ${foo#*/} <= foo에서 처음부터 오직 왼쪽 */ 제거하고 출력
echo ${foo##*/} <= foo에서 처음부터 */ 찾아서 최대한 많이 제거하고 출력
bar=/usr/local/etc/local/networks
echo ${bar%local*} <= bar에서 끝부터 local이 오면 중지
echo ${bar%%local*} <= bar에서 끝부터 계속 local까지 비교 후 중지
exit 0

결과는
bar
fud
usr/bin/X11/startx
startx
/usr/local/etc/
/usr/

모든 *.gif파일을 *.jpg로 바꾸기
#!/bin/sh
for image in *.gif
do
cjpeg $image > ${image%%gif}jpg
done

히어 도규먼트(<<) <= 실제로는 명령이 스크립트로부터 입력을 받고 있음에도 파일이나 키보드로부터 입력을 받아들이는 것처럼 실행(echo를 사용 안할때 도 사용하거나 ed(Text 편집기)명령을 제어함)
#!/bin/sh
cat <<!FUNKY!
hello
this is a here
document
!FUNKY!

결과는
hello
this is a here
document

히어 도규먼트 두번째 예제
파일명 a_text_file
That is line 1
That is line 2
That is line 3
That is line 4

#!/bin/sh
ed a_text_file <<!FunkyStuff! <= 히어 도큐먼트 시작
3 <= a_text_file 3번째 줄로 가기
d <= a_text_file 해당 위치에서 줄 삭제
.,\$s/is/was/ <= 3번째 행이 삭제되었기 때문에 기존 4번째 행에서 is를 was로 변경
w <= 저장
q <= 나가기
!FunkyStuff! <= 히어 도큐먼트 끝
exit 0

결과는
That is line 1
That is line 2
That was line 4

디버그 하기
sh -n <스크립트> <= 문법 검사
sh -v <스크립트> <= 소스 보기
sh -x <스크립트> <= 출력값마다 출력을 위한 소스를 보여줌(가장 좋다)
trap 'echo 변수명 = $변수명' EXIT <= 종료될때 변수값 출력

그래픽으로 보여주기 <= dialog 유틸을 사용(yum install dialog)
diaglog --msgbox "Hello World" 9 18
결과는 사이즈가 넓이 9 높이 18인 Hello World라고 다이얼로그 박스가 나옴
--더이상의 그래픽 부분은 생략함--

댓글 없음:

댓글 쓰기