리눅스 (9) - Shell Programming
리눅스 (9) - Shell Programming
Shell Programming
1) 개요
- Shell Script는 Unix나 Linux, 또는 POSIX를 지원하는 macOS 등에서 사용되는 인터프리터 기반 스크립트 언어이다.
- 리눅스나 유닉스 환경이 갖추어진 곳이라면 어디서든 실행할 수 있다.
- 프로그래밍 언어와 비슷하게 변수, 반복문, 제어문 등을 지원한다.
작성
- 확장자는 생략하거나 직접 정해서 사용해도 되지만, 관례상
.sh를 사용한다. - 파일 최상단에
#!/bin/bash형태의 Shebang을 작성하여 실행 쉘 환경을 지정한다. - 작성예시 (
name.sh) ```bash #!/bin/bash echo “사용자 이름: “ $USER echo “홈 디렉토리: “ $HOME exit 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
* **실행**
* `sh` 명령으로 실행: `sh 파일경로`
* 실행 권한 부여 후 실행: `chmod +x name.sh`
* 스크립트 파일 없이 단일 명령어로 실행: `echo "사용자 이름: " $USER; echo "홈 디렉토리: " $HOME`
---
### 2) 변수
#### 개요
* 변수를 미리 선언할 필요가 없다.
* 최초로 값을 할당할 때 변수가 자동 생성된다.
* 대소문자를 구분하며, 관례적으로 대문자를 자주 사용한다.
* 대입 연산자(`=`) 전후에 공백을 두면 안 된다.
* 별도의 타입 지정이 없으며, 대입하는 값에 따라 문자열이나 숫자로 취급된다.
* 공백이 포함된 문자열은 큰따옴표(`""`)로 묶어야 한다.
#### **변수 선언 및 출력**
* 변수를 참조할 때는 변수명 앞에 `$`를 붙인다.
* 예시 (`variable.sh`)
```bash
#!/bin/bash
language=Korean
echo "I can speak $language"
산술 연산
- 변수에 저장된 값은 기본적으로 문자열로 취급된다.
- 산술 연산을 수행하려면
expr키워드와 백틱(````) 또는$(( ))구조를 사용해야 한다. expr연산 시 항과 연산자 사이에 반드시 공백을 두어야 한다.- 수식 내 괄호
()및 곱하기 연산자*는 백슬래시(\)로 이스케이프해야 한다. ```bash #!/bin/bash
num1=100 num2=$num1+200 echo $num2 # 출력: 100+200 num2=expr $num1 + 200 echo $num2 # 출력: 300 num4=expr $num3 \* 3 echo $num4 # 출력: 900
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
* **위치 매개변수 (Positional Parameters)**
* 스크립트 실행 시 전달되는 인자는 `$숫자` 형태의 매개변수에 할당된다.
* 실행 예시: `sh variable.sh -a --b`
* `$0`: `variable.sh` (실행 파일명)
* `$1`: `-a` (첫 번째 인자)
* `$2`: `--b` (두 번째 인자)
* `$*`: 전체 인자 목록 (`-a --b`)
* `$@`: 전체 인자 목록 (각 인자를 개별 단어로 취급)
* `$#`: 전달된 매개변수의 총 개수
```bash
#!/bin/bash
echo "실행 파일 이름: <$0>"
echo "첫번째 파라미터: <$1> 두번째 파라미터: <$2>"
echo "전체 파라미터: <$*> 이고 개수: <$#>"
3) 함수
개요
- 특정 동작을 수행하는 코드 블록으로, 코드 재사용을 위해 작성한다.
function 함수명() { ... }또는함수명() { ... }형태로 선언한다.- 예시 (
func.sh) ```bash #!/bin/bash
function print() { echo “Hello” }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
* `sh` 명령어 실행 시 호환성 문제가 발생할 수 있으므로 `bash` 명령으로 실행하거나, 실행 권한을 부여한 후 직접 실행(`./func.sh`)한다.
#### **매개변수 및 변수 Scope**
* 함수 내에서도 위치 매개변수(`$1`, `$2` 등)를 사용할 수 있다.
* **전역 변수**: 함수 외부에서 생성하며 스크립트 전역에서 접근 가능하다.
* **지역 변수**: 함수 내부에서 `local` 키워드로 선언하며, 함수 내부로 범위가 제한된다.
```bash
#!/bin/bash
globalvar="전역변수"
function print() {
echo $globalvar
local localvar="지역변수"
echo $localvar
}
echo $globalvar
print
echo $localvar # 출력되지 않음
특수 매개변수
$$: 현재 스크립트 또는 명령어의 프로세스 ID (PID)$?: 최근에 실행된 명령/함수의 종료 상태 (0은 정상 종료)$!: 최근 실행된 백그라운드 작업의 PID$-: 현재 설정된 쉘 옵션 플래그
매개변수 확장 (Parameter Expansion)
- 변수 뒤에 문자열을 이어 쓸 때에는
${변수명}문자열형태로 중괄호를 사용한다. ```bash URL=”www.example.com/” echo “http://${URL}login” # http://www.example.com/login
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#### **변수 초기화 확장자**
* `${var:-default}`: `var`가 비어있거나 unset이면 `default`를 반환 (기존 변수 유지)
* `${var:=default}`: `var`가 비어있거나 unset이면 `default`를 `var`에 할당 후 반환
* `${var:?message}`: `var`가 비어있거나 unset이면 `message` 출력 후 스크립트 종료
* `${var:+alternative}`: `var`에 값이 존재할 때만 `alternative` 반환
#### **문자열 추출 및 길이**
* `${#var}`: 문자열 길이 반환
* `${var:offset}`: `offset` 위치부터 시작하는 문자열 반환
* `${var:offset:length}`: `offset` 위치부터 `length`만큼 자른 문자열 반환
* `${var: -length}`: 뒤에서부터 `length`만큼 자른 문자열 반환 (마이너스 기호 앞 공백 필수)
#### **패턴 삭제 및 경로 추출**
* `${var#pattern}`: 앞에서부터 가장 먼저 일치하는 패턴 삭제
* `${var##pattern}`: 앞에서부터 가장 마지막으로 일치하는 패턴까지 삭제 (파일명 추출)
* `${var%pattern}`: 뒤에서부터 가장 먼저 일치하는 패턴 삭제 (확장자 제거)
#### **치환 및 대소문자 변환**
* `${var/pattern/string}`: 처음 일치하는 패턴을 `string`으로 변환
* `${var//pattern/string}`: 일치하는 모든 패턴을 `string`으로 변환
* `${var^}`: 첫 글자만 대문자로 변환
* `${var^^}`: 전체 문자열을 대문자로 변환
* `${var,}`: 첫 글자만 소문자로 변환
* `${var,,}`: 전체 문자열을 소문자로 변환
---
### 4) 조건문
* **if 문**
* 대괄호 `[`와 조건식 사이에는 반드시 공백이 존재해야 한다.
```bash
if [ 조건식1 ]
then
수행할 내용
elif [ 조건식2 ]
then
수행할 내용
else
수행할 내용
fi
- switch-case 문 ```bash case $변수 in 값1) 수행문1;; 값2) 수행문2;; *) 기본 수행문;; esac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
---
### 5) 반복문
* **for 문**
```bash
# 리스트/배열 순회
for 변수 in 값1 값2 값3
do
수행할 내용
done
# C 언어 스타일
for ((i=0; i<3; i++))
do
수행할 내용
done
- while 문 ```bash num=0 while [ $num -lt 3 ] do echo $num num=$((num+1)) done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
* **제어문 키워드**: `until`, `break`, `continue`, `return`, `exit`
---
### 6) 연산자
#### **문자열 연산자**
* `-z`: 문자열 길이가 0이면 참
* `-n`: 문자열 길이가 0이 아니면 참
#### **비교 연산자**
* 정수 비교: `-eq`, `-ne`, `-gt`, `-ge`, `-lt`, `-le` (`>`, `<` 기호 사용 시 `(( ))` 구문 필요)
* 문자열 비교: `=`, `==`, `!=` (`>`, `<` 기호 사용 시 `[[ ]]` 구문 필요)
#### **논리 연산자**
* AND: `[ 조건1 -a 조건2 ]`, `[ 조건1 ] && [ 조건2 ]`, `[[ 조건1 && 조건2 ]]`
* OR: `[ 조건1 -o 조건2 ]`, `[ 조건1 ] || [ 조건2 ]`, `[[ 조건1 || 조건2 ]]`
#### **파일 및 디렉토리 연산자**
* `-d`: 디렉토리이면 참
* `-e`: 파일/디렉토리가 존재하면 참
* `-f`: 일반 파일이면 참
* `-L`: 심볼릭 링크이면 참
* `-r` / `-w` / `-x`: 각각 읽기 / 쓰기 / 실행 권한이 있으면 참
* `-s`: 파일 크기가 0보다 크면 참
#### **파일 비교 연산자**
* `파일1 -nt 파일2`: 파일1이 파일2보다 최신 파일이면 참
* `파일1 -ot 파일2`: 파일1이 파일2보다 오래된 파일이면 참
* `파일1 -ef 파일2`: 두 파일이 동일한 파일(하드 링크 등)이면 참
---
### 7) 내장 함수 (Built-in Functions)
* **`eval`**: 문자열을 명령문으로 해석하여 실행한다.
* **`export`**: 변수를 환경 변수로 등록하여 자식 프로세스에서도 참조 가능하게 한다.
* **`printf`**: C 언어의 `printf`와 같이 서식화된 출력을 제공한다.
* **`set`**: 명령어의 실행 결과를 파라미터(`$1`, `$2`...)로 할당한다.
```bash
set $(date)
echo "$1" # date 명령어 결과의 첫 번째 항목 출력
8) 정규 표현식 (Regular Expression)
개요
- 특정한 규칙을 가진 문자열의 집합을 표현하는 형식 언어이다.
- 대용량 텍스트에서 특정 패턴을 검색, 추출, 치환할 때 사용한다.
메타 문자
.: 임의의 한 문자 (줄바꿈 제외)^: 줄의 시작$: 줄의 끝|: OR 조건*: 0회 이상 반복+: 1회 이상 반복?: 0회 또는 1회 존재{n}/{n,}/{n,m}: n회 반복 / n회 이상 반복 / n~m회 반복[ ]: 대괄호 내 문자 중 하나와 매칭 (하이픈-은 범위 지정,^는 부정)( ): 그룹화
POSIX 문자 클래스
[:digit:]: 숫자 ([0-9])[:lower:]/[:upper:]: 소문자 / 대문자[:alpha:]/[:alnum:]: 알파벳 / 알파벳 및 숫자[:space:]/[:blank:]: 공백 전체 / 스페이스 및 탭[:print:]/[:graph:]: 출력 가능 문자 (공백 포함 / 공백 제외)
grep 명령어 활용 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# C로 시작해서 U로 끝나는 3글자 단어 검색
grep C.U expression.txt
# q로 시작하고 ?로 끝나는 소문자 단어 검색
grep -E 'q[[:lower:]]*\?' expression.txt
# '-' 뒤에 숫자 2가 1회 이상 반복되고 '-'로 끝나는 패턴 검색
grep -E '\-2+\-' expression.txt
# 라인 시작 기준 영문 5글자 뒤에 공백이 오는 단어 검색
grep -E '^[a-zA-Z]{5}[[:space:]]' expression.txt
# 영문 4글자 이상 6글자 이하로 끝나는 단어 검색
grep -E '[a-zA-Z]{4,6}$' expression.txt
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.