[Bash] Regular Expression

pingping·2021년 1월 14일
0
  • 참고 서적
    -> 리눅스 커맨드라인 쉘 스크립트 바이블

목표

  • 정규표현식을 정의하기
  • 기초 살펴보기
  • 패턴 확장하기
  • 표현식 만들기

정규 표현식

[1] 정의

  • Linux 유틸리티가 텍스트를 걸러내는 데 사용하는 정의 패턴 템플릿

test@test:~/chap20$ ls -al ../.ba*
-rw------- 1 test test 3231 Jan  6 10:58 ../.bash_history
-rw-r--r-- 1 test test  220 Apr  4  2018 ../.bash_logout
-rw-r--r-- 1 test test 3771 Apr  4  2018 ../.bashrc

→ ../.ba* 매개변수는 ls 명령에서 이름이 .ba로 시작하는 파일만 보여주도록 지시한다.

[2] 유형

  • Linux에는 2개의 이닉 있는 정규표현식 엔진이 있다.
    • POSIX 기본 정규표현식
      • sed 편집기는 빨리 데이터 스트림에서 텍스트를 처리하려고 시도하기 때문에 기본 정규표현식은 지원되지 않는다.
    • POSIX 확장 정규표현식
      • gawk 프로그램은 확장 정규표현식 엔진을 사용하여 패턴을 처리한다.

BRE 패턴 정의하기


[1] 일반 텍스트

  • 대소문자 구분
  • 빈 칸 또한 하나의 문자로 간주

Examples

test@test:~/chap20$ echo "This is a test" | sed -n '/test/p'
This is a test

test@test:~/chap20$ echo "This is a test" | sed -n '/guest/p'

test@test:~/chap20$ echo "This is a test" | gawk '/test/{print $0}'
This is a test
  • gawk, sed 모두 대소문자를 구분한다.
test@test:~/chap20$ echo "This is a test" | gawk '/test/{print $0}'
This is a test
test@test:~/chap20$ echo "This is a test" | gawk '/Test/{print $0}'

test@test:~/chap20$ echo "This is a test" | sed -n '/test/p'
This is a test
test@test:~/chap20$ echo "This is a test" | sed -n '/Test/p'
  • 빈 칸 또한 하나의 문자처럼 간주된다.
test@test:~/chap20$ echo "This is number1 channel" | sed -n '/1 c/p'
This is number1 channel

test@test:~/chap20$ echo "This is number1 channel" | gawk -n '/ channel/{print $0}'
This is number1 channel

[2] 특수 문자

  • . * [ ] ^ $ { } \ + ? #

    ⇒ 텍스트 패턴에 이러한 문자를 그대로 사용할 수 없다.

  • 특수 문자를 일반 문자처럼 사용하고 싶으면 이스케이프 ( \ ) 문자를 사용해야 한다.

test@test:~/chap20$ echo "\ is a special character" | sed -n '/\\/p'
\ is a special character
test@test:~/chap20$ echo "\ is a special character" | gawk -n '/\\/{print $0}'
\ is a special character

[3] 앵커 문자

  • 두 가지 특수 문자인 앵커 문자 ( ^, $ ) 를 사용할 수 있다.

1. 처음에서 시작하기

  • 캐럿 문자 ( ^ ) 는 데이터 스트림 안의 텍스트 줄 시작 부분에서 시작하는 패턴을 정의한다.
test@test:~/chap20$ echo "The book store" | sed -n '/^T/p'
The book store

test@test:~/chap20$ cat test3 
this is a test line
hello is a test line
career is a test line
git is a test line
test@test:~/chap20$ sed -n '/^git/p' test3 
git is a test line

3. 마지막에서 찾기

  • 달러 기호 ( $ ) 는 데이터의 줄이 지정된 텍스트 패턴으로 끝나야 한다.
test@test:~/chap20$ echo "This is a test book" | sed -n '/book$/p'
This is a test book

test@test:~/chap20$ cat test3 
this is a test boy
hello is a test woman
career is a test girl
git is a test man
test@test:~/chap20$ sed -n '/man$/p' test3 
hello is a test woman
git is a test man

4. 앵커 결합

  • 텍스트가 없는 패턴에서 두 앵커를 결합하면 데이터 스트림에서 빈 줄을 걸러낼 수 있다.
  • d : 매치된 Line을 Delete한다.
test@test:~/chap20$ sed '/^$/d' test3 
this is a test boy
hello is a test woman
career is a test girl
git is a test man

[4] 점 문자

  • 줄바꿈 문자를 제외한 모든 문자 한 개와 일치시키기 위해 사용한다.
test@test:~/chap20$ cat test3 
this is a test boy
hello is a test woman
career is a test girl
git is a test man

test@test:~/chap20$ gawk '/.man/{print $0}' test3 
hello is a test woman
git is a test man

[5] 문자 클래스

  • 문자 클래스의 문자 중 하나가 데이터 스트림에 있다면 패턴은 일치한다.
  • 대괄호 [ ] 를 사용할 수 있다.
test@test:~/chap20$ cat test3 
There is 3 bottles
i am no.1
you have 5 dishes

test@test:~/chap20$ sed -n '/[123]/p' test3 
There is 3 bottles
i am no.1

test@test:~/chap20$ echo "Yes" | sed -n '/[Yy][Ee][sS]/p'
Yes
test@test:~/chap20$ echo "YeS" | sed -n '/[Yy][Ee][sS]/p'
YeS

[6] 부정형 문자 클래스

  • 클래스에 포함된 문자를 찾는 대신 클래스에 없는 문자를 찾을 수 있다.

    ⇒ 문자 클래스 범위의 시작 부분에 캐럿 문자를 놓으면 된다.

test@test:~/chap20$ sed -n '/^[^a-z]/p' test3
There is 3 bottles

test@test:~/chap20$ sed -n '/^[^A-Z]/p' test3
i am no.1
you have 5 dishes

[7] 범위 사용하기

test@test:~/chap20$ cat test1 
12345
123561
2134
12512
00000
test@test:~/chap20$ sed -n '/^[0-9][0-9][0-9][0-9][0-9]$/p' test1
12345
12512
00000

[8] 특수 문자 클래스

[[:alpha:]]  : 모든 알파벳 글자와 일치
[[:alnum:]]  : 영숫자 및 문자 0-9, A-Z, a-z 와 일치
[[:blank:]]  : 빈 칸이나 탭 문자와 일치
[[:digit:]]  : 0-9까지의 숫자와 일치
[[:lower:]]  : 소문자와 일치 (a-z)
[[:upper:]]  : 대문자와 일치 (A-Z)
[[:print:]]  : 인쇄할 수 있는 모든 문자와 일치
[[:space:]]  : 모든 화이트스페이스 문자와 일치 ( 빈 칸, 탭, NL, FF, VT, CR )
[[:punct:]]  : 문장 부호 문자와 일치
test@test:~/chap20$ echo "abc" | sed -n '/[[:alnum:]]/p'
abc
test@test:~/chap20$ echo "abc" | sed -n '/[[:upper:]]/p'
test@test:~/chap20$ echo "abc" | sed -n '/[[:lower:]]/p'
abc
test@test:~/chap20$ echo "abc123" | sed -n '/[[:digit:]]/p'
abc123

[9] 별표

  • 별표를 놓으면 그 글자가 0번 또는 그보다 많이 나와야 한다.
test@test:~/chap20$ echo "ik" | sed -n '/ie*k/p'
ik
test@test:~/chap20$ echo "iek" | sed -n '/ie*k/p'
iek
test@test:~/chap20$ echo "ieek" | sed -n '/ie*k/p'
ieek
test@test:~/chap20$ echo "ieeek" | sed -n '/ie*k/p'
ieeek

## 이 조합은 어떤 문자가 몇 개든 나와도 일치하는 패턴을 제공한다.
test@test:~/chap20$ echo "this is a regular pattern expression" | sed -n '/regular.*expression/p'
this is a regular pattern expression

확장 정규표현식

  • gawk 프로그램은 확장 정규표현식을 인식하지만 sed 편집기는 인식하지 못한다.
  • gawk 프로그램은 확장 정규식 패턴 기호 대부분을 사용할 수 있으며 sed 편집기에는 없는 추가 필터링 기능을 제공한다.

[1] 물음표

  • 물음표 : 그 앞에 있는 문자가 없거나 한 번 나타나는 것
test@test:~/chap20$ echo "bt" | gawk '/be?t/{print $0}'
bt
test@test:~/chap20$ echo "bet" | gawk '/be?t/{print $0}'
bet
test@test:~/chap20$ echo "beet" | gawk '/be?t/{print $0}'

[2] 더하기 기호

더하기 기호는 문자가 한 번 이상 나타날 수 있지만 한 번 이상은 있어야 한다는 것

test@test:~/chap20$ echo "beeet" | gawk '/be+t/{print $0}'
beeet
test@test:~/chap20$ echo "bet" | gawk '/be+t/{print $0}'
bet
test@test:~/chap20$ echo "bt" | gawk '/be+t/{print $0}'

[3] 중괄호 사용하기

  • 확장 정규표현식에서 사용할 수 있는 중괄호

    • m : 정규표현식이 정확히 m번 나타남
    • m, n : 적어도 m번 나타나지만 n번 보다 많이 나타나지는 않음
    • -re-interval 커맨드라인 옵션을 지정해주어야 인터벌을 사용할 수 있다.

test@test:~/chap20$ echo "bt" | gawk --re-interval '/be{1}t/{print $0}'

test@test:~/chap20$ echo "bet" | gawk --re-interval '/be{1}t/{print $0}'
bet

test@test:~/chap20$ echo "beet" | gawk --re-interval '/be{1}t/{print $0}'

test@test:~/chap20$ echo "beet" | gawk --re-interval '/be{1,2}t/{print $0}'
beet

test@test:~/chap20$ echo "beeet" | gawk --re-interval '/be{1,2}t/{print $0}'

[4] 파이프 기호

  • 파이프 기호는 정규표현식 엔진이 논리 OR 식에 사용할 두 개 또는 그 이상의 패턴을 지정할 수 있다. 패턴 중 어느 것이든 데이터 스트림의 텍스트와 일치한다면 텍스트는 일치 패턴을 통과함
test@test:~/chap20$ echo "The cat is sleeping" | gawk '/cat|dog/{print $0}'
The cat is sleeping

test@test:~/chap20$ echo "The dog is sleeping" | gawk '/cat|dog/{print $0}'
The dog is sleeping

test@test:~/chap20$ echo "The sheep is sleeping" | gawk '/cat|dog/{print $0}'

[5] 표현식 그룹화하기

  • 정규식 패턴은 또한 괄호로 그룹화할 수 있다.
# 완전한 영어 단어인 Saturday나 그 약칭인 Sat 중 어느 것이든 받아들인다.

test@test:~/chap20$ echo "Sat" | gawk '/Sat(urday)?/{print $0}'
Sat

test@test:~/chap20$ echo "Saturday" | gawk '/Sat(urday)?/{print $0}'
Saturday

정규표현식 실제 활용하기

[1] 디렉터리 파일 세기

  • PATH 환경 변수는 각 디렉터리가 콜론으로 구분되어 있다.
  • 각 콜론을 빈칸으로 대체하여 for문으로 돌려 사용해볼 것이다.
test@test:~/chap20$ echo $PATH | sed 's/:/ /g'
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games /snap/bin

Example

test@test:~/chap20$ cat countfiles.sh 
#!/bin/bash

# Count number of files in your PATH

mypath=$(echo $PATH | sed 's/:/ /g')

count=1

# 1차 for문
for directory in $mypath
do
	# ls 출력 결과를 check 변수에 저장
	check=$(ls $directory)
	# 2차 for문
	for item in $check
	do
		# 갯수 1개씩 증가
		count=$[ $count + 1]
	done
	echo "$directory has $count files"
	count=0
done

test@test:~/chap20$ ./countfiles.sh 
/usr/local/sbin has 1 files
/usr/local/bin has 0 files
/usr/sbin has 156 files
/usr/bin has 703 files
/sbin has 225 files
/bin has 170 files
/usr/games has 0 files
/usr/local/games has 0 files
/snap/bin has 6 files

[2] 전화번호 검증하기

## 허용 가능 전화번호 Pattern
# 000-0000-0000
# 000 0000 0000
# 000.0000.0000
# 00012345678

test@test:~/chap20$ cat isPhoneNum.sh
#!/bin/bash

# 010-1234-5678

gawk --re-interval '/[0-9]{3}(| |-|\.)[0-9]{4}(| |-|\.)[0-9]{4}/{print $0}

test@test:~/chap20$ echo "317-4555-1234" | ./isPhoneNum.sh 
317-4555-1234
test@test:~/chap20$ echo "317 4555 1234" | ./isPhoneNum.sh 
317 4555 1234
test@test:~/chap20$ echo "317.4555.1234" | ./isPhoneNum.sh 
317.4555.1234
test@test:~/chap20$ echo "31745551234" | ./isPhoneNum.sh 
31745551234
profile
Cloud Infra Engineer & interested in python, IaC, k8s

0개의 댓글