if 문

지정된 명령어를 실행하여 종료상태가 0 이면 참으로 판단하고 그 외에는 거짓으로 판단

 

셸 스크립트 예시

if-bin.sh

#!/bin/bash

if [ "$1" = "bin" ]; then   # 해석 : 커맨드 라인에서 인자 1이 "bin" 이면 OK 출력
   echo "OK"
ellif [ "$1" = "hello" ]; then
   echo "Hello" 
else
   echo "NG"
fi

  ▶ if 뒤에는 조건문이 아닌 명령어 

  ▶ [ 가 명령어 : [ 뒤에 오는 "$1", "bin",  ] 모두 명령어 [ 의 인자

  ▶ 문법상의 주의점
         띄어쓰기
         - [ ] 안의 문자열 간의 공백 필수

         - if 와 [ 사이에 공백

         - if [   ] 후에 세미콜론(;)

사용

$ ./if-bin.sh "bin"
OK

  

● 명령어의 종료상태 확인 코드

$ echo $?     # 직전에 사용한 명령어의 종료 상태 출력

  ▶  종료 상태면 0, 에러가 발생하면 0 이외의 값 출력

$ [ "$1" = "bin" ]   # 조건식 명령어 실행 : 참이면 0, 아니면 0 이외의 값 
$ echo $?            
1                    # 조건식 뒤에 아무 값이 없으므로 1 출력

  ▶  if 문도 참이면  0, 에러가 발생하면 0 이외의 값 출력

#!/bin/bash

if [ -z "$1" ]; then
   exit 1         
fi

  exit 를 이용하여 출력할 종료상태를 지정

 test 명령어

if [ "$1" = "bin" ]; then      
if test "$1" = "bin";  then 

  둘 다 같은 의미를 지님

 연산자

문자열 비교

연산자 내용
str1 = str2 str1 과 str2 가 같음 
str1 != str2 같지 않음
-n str1 빈 문자열이 아님
-z str1 빈 문자열임 → 빈 문자열이면 참 

 

정수 비교 - 오직 정수만 다룸

연산자 내용
1 -eq 2 같다
1 -ne 2 같지 않다
1 -lt 2 < , 1 이 2 보다 작음
1 -le 2 ≤ , 1 이 2 이하임
1 -gt 2 > , 1 이 2 보다 큼 
1 -ge 2 ≥ ,  1이 2 이상임

 

파일 속성

연산자 내용
-e < file 명> < file 명> 존재
-d < file 명> < file 명> 존재하고 디렉터리임
-h < file 명> < file 명> 존재하고 심볼릭 링크임
-L < file 명> < file 명> 존재하고 심볼릭 링크임
-f < file 명> < file 명> 존재하고 일반 파일임
-r < file 명> < file 명> 존재하고 읽기 권한이 부여되어 있음
-w < file 명> < file 명> 존재하고 쓰기 권한이 부여되어 있음
-x < file 명> < file 명> 존재하고 실행 권한이 부여되어 있음
< file 명1 > -nt < file 명 2 > < file 명 1 > 의 변경 시각이 < file 명 2> 보다 최근임
< file 명 1 > -ot < file 명 2 > < file 명 1 > 의 변경 시작이 < file 명 2 >  보다 오래됨

 

결합 연산자

연산자 내용
조건식 1 -a 조건식2 두 조건식이 참이면 참 (and)
조건식 1 -o 조건식2 두 조건식중 하나가 참이면 참(or)
! 조건식 조건식의 진위값을 반대로 함(not)
() 조건식을 그룹화



&& 와 ||

명령어 1 && 명령어 2 : 명령어 1이 정상종료하여야 명령어2를 실행

$ [ -f file.txt ] && cat file.txt

 

명령어 1 || 명령어 2 : 명령어 1이 정상종료하지 않아야 명령어2를 실행

$ [ -f file.txt ] || touch file.txt

변수

 

쿼팅 (quoting)

따옴표로 문자열을 묶는 행위

 

▨ "" 와 '' 의 차이

 

명령어 치환

▨ 명령어 치환 → $()

#!/bin/bash

filename = $(date '+%Y-%m-%d')
touch "$filename"
$ echo "Today is $(date '+%Y-%m-%d')"
Today is 2024-04-09

 

 

위치 파라미터

$1, $2 → 커맨드 라인 인자의 값(위치 파라메터)

parameter.sh

#!/bin/bash

echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$4 = $4"
echo "\$5 = $5"
echo "\$# = $#"  # 지정한 인자의 총 개수를 확인하는 방법 $#

 

▨ command line 에 인자 3개를 지정하여 실행 

$ ./parameters.sh aaa bbb ccc
$0 = ./parameters.sh
$1 = aaa
$2 = bbb
$3 = ccc
$4 =
$5 =
$# = 3

 

▨ 와일드카드 * 사용

$ ls
drink2.txt    homesize.sh   parameters.sh score.csv
$ ./parameters.sh *
$0 = ./parameters.sh
$1 = drink2.txt
$2 = homesize.sh
$3 = parameters.sh
$4 = score.csv
$5 =
$# = 5

 

▨ 인자 전체 조회 → $@,  $*

args.sh

#!/bin/bash

echo "\$@ = $@"
echo "\$* = $*"

 

실행

$ ./args.sh aaa bbb ccc "hello"
$@ = aaa bbb ccc hello
$* = aaa bbb ccc hello

- 출력이 같아 보이지만 사실상 아래와 같이 출력됨

   $@ = "aaa" "bbb" "ccc" "hello" : 각 각의 문자열

   $* = "aaa bbb ccc hello"   : 하나의 문자열

 

셸 스크립트 작성

원하는 파일을 생성  ( 파일명.sh)   

 ✓ ".sh" 는 쉘 스크립트라는 것을 알 수있도록 확장자 지정한 것

#!/bin/bash
echo "Hello"
ls -a

      - #!/bin/bash  :  셔뱅(shebang)은 #!

  • 셔뱅 :  셸 스크립트 파일을 작성할때  최상단에 작성하는 문구 중 #!  
    • 파일의 최상단에 위치
    • 그담에 오는 명령어로 해당 쉘 스크립트를 무엇으로 실행할 것인지 명시하는 역할
    • #!/bin/bash → bash 로 해당 쉘 스크립트를 실행

실행 권한 부여

$ chmod +x shellScript.sh

 

실행

# 3가지 방법 다 동일하게 작동
$ ./shellScript.sh
$ bash ./shellScript.sh 
$ source ./shellScript.sh

✓  두번째와 세번째 실행 방식은 파일에 셔뱅으로 bash 를 지정 안해도 실행 가능

 

실행 방법에 의한 차이

파일 이름만으로 실행

 셔뱅에 무엇을 이용하여 파일을 실행할 것인지 명시 필요

셸의 인자로 지정하여 실행

 이미 bash 로 실행하겠다고 지정하여서 shebang에 지정을 안해도 실행가능

source 명령어를 이용한 실행

 위 두가지 방식과 동작방식 상의 차이점 존재

→ 현재 설정된 shell 을 기준으로 파일에 기재된 커맨드 라인이 실행

현재 shell 에 설정된 환경에 영향을 받음 : 설정된 별명을 스크립트 안에서 사용가능

 현재 shell 환경에 영향을 줌 : 별명을 설정가능, 터미널이 재실행되면 설정된 별명 존재 안함

 

※ 예시

test.sh 

"""""""

#!/bin/bash

alias lsalf='ls-alF'

"""""""

$ lsaf
명령을 찾을 수 없습니다.
$ source ./test.sh
$ lsaf
실행된 결과 출력

 

    >> 터미널을 재 시작하고 lsaf 를  쳐보면 별명이 설정 안되어 있다는것을 확인 가능

 

shell script 배치용 디렉터리

셸 스크립트를 cat  이나 ls 처럼 이름 만으로 실행가능한 방법

 

1. 셸 스크립트를 ~/bin 으로 이동

$ mkdir ~/bin
$ mv homesize.sh ~/bin

 

2.  vim 으로 ~/.profile 에 내용추가

$ vim ~/.profile
....
....
PATH = "$PATH: ~bin"
...

 

3. 재시작후 source 명령어 실행하여 검색 경로에 추가

$ source ~/.profile

 

▶▶▶  어디에서든지  파일명으로 실행가능

 

 

 

패턴 검색 및 처리 언어

awk '패턴 { 액션 }' 파일

 

 < 동작 방식 >

* 패턴이 생략되면 모든 레코드에 대한 액션이 실행

  1. 파일에 있는 1행을 읽음
  2. 레코드를 획득
    • 예를 들어 파일에
       -----
        ber
        beer
       ----
      가 있으면
      1행 읽으면 -> 레코드 'ber' 를 획득
  3. 패턴에 부합한지 확인
    • 부합하면 액션을 실행
    • 부합자지 않으면 아무것도 하지 않음
  4. 2행을 읽음 

필드변수  

awk : 특정 필드를 추출할 때 많이 사용

 

▶ awk의 필드 변수

# 전체 : $0
-rwxr-xr-x  1  root   wheel  100928  3   21   15:13   yes
#   $1      $2  $3     $4      $5   $6   $7    $8     $9
#                                     $(NF-2) $(NF-1) $NF

 

▶ ls 명령어 결과에서 5번째와 9번째의 필트 출력

$ ls -l /usr/bin | awk '{print $5, $9}'
171824 AssetCacheLocatorUtil
227584 AssetCacheManagerUtil

$ ls -l /usr/bin | awk '{print $5 $9}' # , 삭제되어서 두 필드가 붙어서 출력
171824AssetCacheLocatorUtil
227584AssetCacheManagerUtil
...

 

▶  레코드의 마지막 필드 출력 : $NF

$ ls -l /usr/bin | awk '{print $(NF-1), $NF}'
15:13 AssetCacheLocatorUtil
15:13 AssetCacheManagerUtil
...

 

패턴 지정  

▶  9 번째 필드가 cp 로 시작하는 것만 출력

awk '$9 ~ /^cp/ {print $5, $9}'

      ~         : 비교

     / ^cp /  : 정규표현식 cp

 

액션 생략

액션을 생략하면 단순히 레코드를 출력 → {print $0} 이 실행

▶  같은 결과가 나오는 코드

$ awk '$9 ~/^cp/'
$ awk '$9 ~/^cp/ {print}' 
$ awk '$9 ~/^cp/ {print $0}'

csv 파일 총합 과 평균

▶  총합

$ awk -F, '{sum += $NF} END {print sum}' score.csv
323

-F 는 필드 구분자를 셋팅하는 옵션 → -F, : , 을 필드 구분자로 설정

 

▶  평균

$ awk -F, '{sum += $NF} END {print "Average:",sum/NR}' score.csv
Average: 53.8333

배우는 내용 : [ sed 삭제(d), 출력(p), 치환(s) ]

sed

vim 과 sed 비교

  vim sed
1 파일 열기 셸에서 편집내용(스크립트) 을 입력 
2 메모리상에서 편집  편집
3 저장 편집 결과를 표준 출력에 출력 (저장 x)

sed 명령어 

sed [옵션] <스크립트> <대상 파일>

 <스크립트> : 주소(정규 표현식도 가능)와 명령어를 조합한 문자열, 주소가 없으면 모든 행에대해 명령어가 실행된다.

동작방식:

한 행을 읽으면 먼저 패턴 스페이스라는 장소에 복사

편집 명령어를 실행한 뒤 패턴 스페이스의 내용을 출력

기본적으로 패턴 스페이스에 있는 내용을 자동으로 출력

* 패턴 스페이스 (패턴 버퍼) : 현재 작업중인 텍스트의 임시 저장 공간

<실습파일 내용>

Ber
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeer!!!
My Vodka
My Wine

 

삭제  ( d )

$ sed 1d drink2.txt   # 첫 번째 행을 삭제
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeer!!!
My Vodka
My Wine

$ sed 2,5d drink2.txt  # 2 행부터 5행까지 삭제
Ber
My Vodka
My Wine

$ sed '3,$d' drink2.txt # 3행 부터 마지막 행까지 삭제
Ber
Beer

$ sed /^B/d drink2.txt # B로 시작하는 행 삭제
My Vodka
My Wine

 - $ 는 마지막 행을 의미

 

출력 ( p )

$ sed 1p drink2.txt # 1행을 출력
Ber
Ber
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeer!!!
My Vodka
My Wine

 sed는 기본적으로 패턴 스페이스의 내용을 출력

    1. sed 는 해당 파일의 각 줄(행)을 순차적으로 읽어 패턴 스페이스에 로드

    2. 1p 명령에 따라  1행이 추가로 출력 

    3. -n 옵션의 부재로 모든 행을 출력

 

$ sed -n 1p drink2.txt 
Ber

치환 ( s )

's/(치환 전 문자열)/(치환 후 문자열)/옵션'
$ sed 's/Beer/Whisky/' drink2.txt
Ber
Whisky
WhiskyBeer
WhiskyBeerBeer
Beeeeeeeeer!!!
My Vodka
My Wine

$ sed 's/Beer/Whisky/g' drink2.txt # g 옵션 포함
Ber
Whisky
WhiskyWhisky
WhiskyWhiskyWhisky
Beeeeeeeeer!!!
My Vodka
My Wine

$ sed 's/^B.*r/Whisky/g' drink2.txt  # B로 시작하고 r로 끝나는 문자열 치환
Whisky
Whisky
Whisky
Whisky
Whisky!!!
My Vodka
My Wine

 'g' : 발견한 모든 문자 치환

 

명령어 조합

$ sed 's/!//g' drink2.txt      # !를 전부 삭제
Ber
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeer
My Vodka
My Wine

$ sed -n 's/!//gp' drink2.txt  # -n : 치환된 행만 출력 
Beeeeeeeeer

# 1행과 3행 사이의 문자열 중에서 Beer 를 Whisky로 치환
$ sed '1,3s/Beer/Whisky/g' drink2.txt 
Ber
Whisky
WhiskyWhisky
BeerBeerBeer
Beeeeeeeeer!!!
My Vodka
My Wine

 'g' : 발견한 모든 문자 치환

 

확장 정규 표현식 사용 -r

- 기본 정규 표현식과 확장 정규 표현식

$ sed -r 's/Be+r/Whisky/' drink2.txt
Whisky
Whisky
WhiskyBeer
WhiskyBeerBeer
Whisky!!!
My Vodka
My Wine

$ sed 's!Be\+r!Whisky!' drink2.txt
Ber
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeer!!!
My Vodka
My Wine

 # s 뒤에 ! 혹은 %를 이용하여 구분자(/)를 바꿀 수 있다.

 

치환 전 정규 표현식을 통해 치환 후 문자열을 \1 로 참조하는 방법

기본 정규 표현식 확장 정규 표현식
\(\) 로 그룹화 하여 \1 로 참조 ()로 그룹화 하여 \1 로 참조

 

$ sed -r 's!My (.*)!--\1--!'
Ber
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeer!!!
--Vodka--
--Wine--

sed 's/My \(.*\)/--\1--/' drink2.txt
Ber
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeer!!!
--Vodka--
--Wine--

+ Recent posts