Shell 스 크 립 트 빠 른 입문

33012 단어
저자: Phosphorus 15
글 목록
  • 변수 와 함수
  • 변수
  • 함수 정의
  • 명령 과 IO
  • 연산 과 절차 제어
  • 연산 과 괄호
  • 분기 문
  • 순환 문
  • 부가 내용
  • 수조
  • 소결
  • shell 스 크 립 트 는 모든 Liux 개발 자 에 게 필요 한 기능 으로 다른 스 크 립 트 언어 에 비해shell 은 Liux 자체 에 더욱 가 깝 고 bash 와 고도 로 통합 되 며 많은 응용 에서 (특히 텍스트 처리 와 IO 와 관련 된) 더욱 높 은 용이 성과 간결 성 을 가진다.
    본 고 를 읽 는 데 일정한 기초 가 필요 하 다. 필 자 는 글 을 쓸 때 독 자 를 기대한다.
  • 일정한 Liux 사용 경험 이 있 습 니 다
  • 최소 하나의 일반적인 스 크 립 트 언어/프로 그래 밍 언어
  • 파이프 가 무엇 인지 알 고 있 습 니 다.
  • 읽 으 면서 잠 들 지 마 세 요. 전문 리듬 이 빠 르 고 세부 적 인 부분 에 대해 지나치게 논술 하지 않 습 니 다 (작가 도 덜렁이 이기 때 문 입 니 다). 독자 가 짧 은 시간 에 빨리 손 을 쓰 게 하 는 데 목적 을 둡 니 다. 만약 에 문제 가 있 으 면 지적 교 류 를 환영 합 니 다.이 글 은 원고 가 되 지 않 아 묘사 오류 가 있 거나 고려 가 주도면밀 하지 못 한 상황 이 있 을 수 있 으 며 내용 도 매우 완비 되 지 않 았 으 니 독자 들 이 많이 양해 해 주시 기 바 랍 니 다.

  • 변수 와 함수
    변량
    변수 정의 와 할당 의 표준 형식 은 = 이 고 단독 성명 이 필요 하지 않 습 니 다. 등호 근처에 빈 칸 이 있 으 면 안 됩 니 다. 예 를 들 어 다음 과 같 습 니 다.
    #!/bin/bash
    
    a=35
    name="williams"
    _o="o"
    _ld='ld'
    _old="$_o$_ld" #    `$`       (         )
    
    echo $name is $a years $_old #   
    
    unset _o #     (  )
    
    sh 명령 으로 스 크 립 트 를 실행 하여 출력 을 얻 습 니 다.
    williams is 35 years old
    

    함수 정의
    함수 의 정의 방식 은 다음 과 같다.
    func1() {
        echo $1 # $1           
        echo $# # $#          
    }
    
    func2() {
        return $(($1+$2)) #                 (        )
    }
    
    a=3
    func1 "oops" 233 #     
    func2 $a 2
    
    echo $? #        /      
    

    스 크 립 트 실행, 출력 획득
    oops
    2
    6
    

    명령 과 IO
    명령 과 IO 는 shell 스 크 립 트 에서 가장 중요 한 부분 으로 파이프 시스템 의 도움 을 받 아 스 크 립 트 는 시스템 명령 과 프로그램 과 쉽게 상호작용 할 수 있 습 니 다.
    다음은 간단 한 예 이다.
    txts=`ls | egrep *.\.txt` #   ls        ,  egrep  .txt  
    #       txts=$(ls | egrep *.\.txt)
    echo $txts #      txt   
    

    이 곳 의 '기 호 는 Ruby 과 비슷 하여 명령 을 실행 하고 의 내용 을 문자열 값 으로 되 돌려 줍 니 다.
    따라서 우리 가 얻 은 변 수 는 txts 이 bash 에서 명령 을 수행 할 때 콘 솔 에서 출력 하 는 내용 입 니 다.
    예 를 들 어 파일 내용 을 읽 거나 현재 사용 자 를 가 져 오 면 상기 방법 을 이용 하여 쉽게 실현 할 수 있다.
    text=`cat hello.txt` # => text      hello.txt     
    username=`whoami` # => username          
    echo $username # =>      ,  root
    

    파일 에 출력 하 는 것 도 간단 하 다.
    text1="hello,"
    text2="world!"
    echo -n $text1 > hello.txt #         (n      )
    echo $text2 >> hello.txt #      hello.txt 
    

    위 스 크 립 트 를 실행 하면 디 렉 터 리 에 hello.txt 이 나타 납 니 다. 그 안에 한 줄 의 텍스트 가 있 습 니 다: hello,world!read 명령 을 사용 하면 콘 솔 에서 변 수 를 읽 을 수 있 습 니 다 (Haskell 과 유사 한 read)
    #!/bin/bash
    # A + B Problem ~
    read a
    read b
    c=$(($a+$b))
    echo $a + $b = $c # => e.g. 1 + 3 = 4
    

    주의해 야 할 것 은 변수 도 ` 기호 에 포 함 된 명령 에 참여 할 수 있다 는 것 이다. 예 를 들 어:
    text="eureka!"
    text=`echo $text | tr 'a-z' 'A-Z'` #  tr             
    echo $text
    

    상기 스 크 립 트 출력 은 EUREKA! 입 니 다.
    연산 및 프로 세 스 제어
    연산 과 괄호shell 스 크 립 트 의 연산 을 언급 하면 가장 자주 사용 하 는 괄호 몇 가 지 를 소개 해 야 한다.
    쌍 소괄호 (( )) 은 산술 (정형) 연산 에 사용 되 는 동시에 일부 특수 기능 에 도 사용 할 수 있다.
    a=2
    b=$(( ($a + 1) / 2 )) # => b = (2 + 1) / 2 = 1
    rd=$((RANDOM % 100)) # => rd  0~99    
    c=$(( $a > 1 )) # =>    a > 1 ,    1 (true)
    d=$(expr $a + $b) # =>     $(($a + $b))
    

    중 괄호 [ ] 과 이중 괄호 [[ ]] 은 비교 연산 에 사용 되 는데 그 중에서 [ ] 은 실제 적 으로 Liux 에서 test 명령 에 대한 암시 적 호출 이다 (반드시 주의해 야 한다: 셸 의 정의 에서 true 은 0 이 고 false 은 1 이다).
    a=2; b=1; c=3; #               
    str='ray-tracing'
    
    [ $a -gt $b ] #        , [$a -gt $b]      
    echo $? #         $?   =>     0 (true)
    
    [ $c -eq $c ] #     test $c -eq $c
    echo $? #     0 (true)
    
    [ $a -ne 1 -a $c -eq 3 ] #        a != 1 && c == 3
    [ $a -ne 1 -o $c -ne 3 ] #        a != 1 || c != 3
    
    [ $str != 'ray-tracing' ] #     1 (false)
    [ $str = 'ray' ] #     1 (false)
    
    [[ a + b = 3 && a != b ]] #     0 (true)
    #       bash    
    
    test 명령 의 사용 을 익히 는 것 은 정확 한 논리 연산 표현 식 을 쓰 는 데 도움 이 되 므 로 독자 들 은 위 키 피 디 아 를 참고 하여 더 많은 것 을 알 수 있다.
    이중 괄호 [[ ]] 은 중 괄호 보다 인성 화 되 어 C 과 비슷 한 표현 식 을 쉽게 감당 할 수 있 음 을 알 수 있다.
    대괄호 {} 은 범위 와 배 치 를 정의 하 는 데 사용 되 는데 여기 서 상세 하 게 논술 하지 않 고 관심 이 있 는 독 자 는 이 블 로 그 를 참고 할 수 있다.
    분기 문Python 과 달리 셸 스 크 립 트 는 어떠한 형식의 들 여 쓰기 도 강요 하지 않 기 때문에 프로 세 스 문 구 는 끝 기호 가 있어 야 합 니 다.
    전형 적 인 if 문 구 는 다음 과 같다.
    read a
    echo -n $a is
    
    b=$(( $a % 2 ))
    if [ $b -eq 0 ]; then #    a      
    	echo " even"
    else
    	echo " odd"
    fi
    
    if [ `whoami` = 'root' ]; then
    	echo "and you are root ?"
    elif [ `whoami` = 'phosphorus15' ]; then #     C    else if
    	echo "seriously ?"
    else
    	echo "alright ~"
    fi
    

    메모: 순환 이 든 분기 제어 든 빈 블록 이 있 으 면 안 됩 니 다. 즉, 나타 나 면 안 됩 니 다.
    if [ `whoami` = 'root' ]; then #     !
    else
    	echo "oops !"
    fi
    

    순환 문
    많은 고급 언어 와 마찬가지 로 셸 은 몇 가지 사용 가능 한 순환 제어 구 조 를 가지 고 필 자 는 여기 서 자신 이 자주 사용 하 는 몇 가 지 를 소개 할 것 이다.
  • while 문장 - 귀 에 익 으 면 자세 하고 말 하지 않 으 면 ~
    a=1; b=0;
    while [ $a -le 100 ]; do	#        while (( $a <= 100 )); do
    	b=$(($a+$b))
    	a=$(($a+1)) # bash      ((a++))
    done
    echo $b #     5050
    
  • until 구문 - 반대로
    a=1; b=0;
    until [ $a -gt 100 ]; do
    	b=$(($a+$b))
    	a=$(($a+1))
    done
    echo $b #     5050
    
    은 사실 while 를 거꾸로 쓰 는 거 예요. 너무 힘 들 지 않 아 요?괜찮아 ~ 산술 연산 은 원래 셸 스 크 립 트 의 특기 가 아니 야. 다음은 네가 볼 것 이 야 말로 셸 의 진정한 정수 야.
  • for each 구문 - C11
    for i in Apple Juice Cake; do
    	echo do you like $i ?
    done
    
    for j in `seq 0 3`; do
    	echo $j
    done
    
    for k in `seq 65 70`; do
    	echo $k | awk '{printf("%c", $1)}' #  ascii       
    	# bash       printf,   printf \\x$(printf %x $k)
    done
    
    for c in {0..8..2}; do # 0~8       
    	echo $c
    done
    #   ,      bash   
    
    출력 내용:
    do you like Apple ?
    do you like Juice ?
    do you like Cake ?
    0
    1
    2
    3
    ABCDEF
    
    예상 하기 어렵 지 않 습 니 다. 우리 의 이전 while 순환 은
    s=0
    for i in `seq 1 100`; do #      1   100    
    	s=$(($s+$i))
    done
    echo $s
    
    을 쓸 수 있 습 니 다. 만약 에 우리 가 디 렉 터 리 에 있 는 모든 파일 에 백업 을 만 들 려 면 이렇게 쓸 수 있 습 니 다.
    for file in $(ls); do #       
            #   file         ,        
            if [ "$(file $file | grep -o directory)" != 'directory' ] 
            then
                    cp $file "$file.bak" #   cp     
                    echo backup $file
            fi
    done
    
  • for 문장 - 음...?필 자 는 앞에서 여러 차례 말 했 듯 이 일부 문 구 는 bash 의 지 지 를 받 을 수 있 을 뿐 sh 의 지 지 를 받 을 수 없다.스 크 립 트 를 sh 으로 실행 하 는 습관 이 많은 것 을 감안 하여 스 크 립 트 를 작성 할 때 이러한 문 구 를 사용 하 는 것 을 피해 야 합 니 다.표준 for 문 구 는 bash 만 지원 할 수 있 습 니 다. 쓰 는 방법 은 다음 과 같 습 니 다.
    for((i=0;i<10;i++));
    do
    	echo $(expr 10 - $i) #     $((10 - $i))
    done
    
    ~ 아 ~ Old good days, ~ 짙 은 C 의 맛 이 물씬 풍 깁 니 다.그래도 상술 한 바 와 같이 사용 을 추천 하지 않 습 니 다.

  • 부가 내용
    배열
    배열 은 bash 에서 만 사용 할 수 있 는 기능 으로 많은 언어 에서 배열 과 매우 비슷 하 다.정의 방식 은 다음 과 같 습 니 다.
    a=(2 7 5 6 8 1 3 0 4 9)
    
    b=({0..9}) # 0 1 2 3 4 5 6 7 8 9
    c=({0..9..2} {1..9..2}) # 0 2 4 6 8 1 3 5 7 9
    
    strs=("tomato" "potato" "onion" "lettuce" "okra")
    misc=("str1" 1 "str2" 5 1)
    

    배열 은 아래 표 시 를 통 해 직접 접근 하거나 펼 칠 수 있 습 니 다.
    echo ${a[0]} ${a[3]} # =>    2 6
    echo ${b[@]} # =>    b       ,  : 0 1 2 3 4 5 6 7 8 9
    
    b[0]=10 #          10
    
    echo ${b[@]} # =>    b       ,  : 10 1 2 3 4 5 6 7 8 9
    echo ${#misc[@]} # =>    misc    ,  5
    echo ${strs[@]:1:3} # =>     1~3    ,  : potato onion lettuce
    
    unset c[3] # =>       3    
    

    이에 따라 for each 순환 으로 배열 을 빠르게 옮 겨 다 닐 수 있 습 니 다.
    for e in ${c[@]}; do
    	echo -n "$e "
    done
    #              ,      0 2 4 8 1 3 5 7 9
    

    작은 매듭
    이로써 독 자 는 기본 셸 스 크 립 트 작성 의 기본 기 교 를 익 혔 을 것 이다. 만약 에 더욱 숙련 되 려 면 독자 스스로 간단 한 스 크 립 트 를 써 서 이 해 를 깊이 있 게 하 는 것 을 추천한다.또한 Liux 시스템 의 관련 명령 도 더 잘 알 아야 한다.
    마지막 으로 필 자 는 상술 한 내용 을 복습 하 는 작은 발 을 내 놓 았 다.
    #!/bin/sh
    factorial() {
        if [ $1 -eq 0 ]; then return 1; fi
        s=1
        for i in `seq 1 $1`; do
        	s=$(($s*$i)) #   
        	trace[$(expr $i - 1)]=$s #       
        done
        echo calculation trace [${trace[@]}] #   
        return $s
    }
    
    if [ `whoami` = 'root' ]; then
    	echo root is not allow to execute this script!
    	exit
    fi
    
    if [ $# -lt 2 ]; then
    	echo usage : sh fac.sh [n] [output] > /dev/stderr #       
    elif [ $1 -lt 0 ]; then
    	echo n cannot be less than zero ! > /dev/stderr
    elif [ -z "$2" ]; then #       
    	echo output file cannot be null ! > /dev/stderr
    else
    	factorial $1
    	echo $1!=$? > "$2"
    fi
    

    스 크 립 트 실행 결과:
    phosphorus15@ubuntu:~/Documents$ sh fac.sh 
    usage : sh fac.sh [n] [output]
    phosphorus15@ubuntu:~/Documents$ sh fac.sh 1
    usage : sh fac.sh [n] [output]
    phosphorus15@ubuntu:~/Documents$ sh fac.sh 1 fac.txt
    calculation trace [1]
    phosphorus15@ubuntu:~/Documents$ file fac.txt
    fac.txt: ASCII text
    phosphorus15@ubuntu:~/Documents$ cat fac.txt
    1!=1
    phosphorus15@ubuntu:~/Documents$ sh fac.sh 5 fac.txt
    calculation trace [1 2 6 24 120]
    phosphorus15@ubuntu:~/Documents$ cat fac.txt
    5!=120
    phosphorus15@ubuntu:~/Documents$ sudo sh fac.sh 5 fac.txt
    [sudo] password for phosphorus15: 
    root is not allow to execute this script!
    

    좋은 웹페이지 즐겨찾기