반응형

awk
데이터 처리를 위한 유닉스 프로그래밍 언어.
awk 이름의 의미는, 언어 개발자 세 명의 이름의 이니셜을 따서 만든 것..
awk가 제작된 이후 다양한 버전이 나왔는데 구버전은 awk, 새로운 버전은 nawk, GNU 버전은 gawk 라는 명령어로 사용한다.

 

awk 기본 사용법

패턴과 command로 이루어진다.
패턴 부분에는

  - 정규식이나 조건 표현식(true/false)이 올 수 있다.

    1. 정규식 예: /^hello$/
    2. 조건 표현식 예: $1 >= 0


command 부분은 
  - c언어와 마찬가지로 조건연산자, 반복연산자, 산술연산자, 논리연산자, 삼항연산자, 증감연산자, 대입연산자 등을 사용 가능하다

  - 문법 또한 c언어와 거의 유사하다.
아무 command를 지정하지 않을 경우, 패턴에 매칭된 줄을 그대로 출력하는 기본 동작을 수행한다.
command 부분은 { }로 감싼다.
command 예: { if($1 >= 0){ print "hello"; } }


정규표현식
    - 정규표현식을 사용할 때는 슬래시 /로 감싼다.
    - grep, sed와 마찬가지로 정규표현식 메타문자를 사용할 수 있다.

※  단 단어 지시자 \<\>, 캡처 \(\), 반복 지시자 \{\}는 사용할 수 없다

 

$ awk '/^Hello/' file # 정규식 /^Hello/에 매칭되는 줄을 그대로 출력한다.

Field Separator
awk는 필드 구분자를 기준으로 각 줄의 필드를 나누어 처리한다. 필드 구분자는 FS라는 이름의 내장변수로 관리되며 기본값은 탭/스페이스이다.

 

 $ cat file
Hello 1  
Hi 2      
Haha 3 

 $ awk '{print $1}' file
hello
hi
haha

 

디폴트 FS인 스페이스에 의해 필드가 나뉘었다. print 함수를 이용하여 첫 번째 필드 $1를 출력한다. command 부분은 { }로 묶는다.

 

 $ cat file
Hello 1  
Hi 2      
Haha 3 

$ awk '/hello/{print $1,$2}' file
hello 1


정규식 패턴 /hello/에 매칭된 모든 줄의 첫 번째 필드($1)와 두 번째 필드($2)를 출력한다. 이 때 $1,$2 사이에 콤마,를 사용했는데, 출력된 결과에는 콤마 대신 공백이 들어갔다. print 명령에서의 콤마는 출력 필드 구분자를 의미하는 OFS라는 이름의 내장변수의 값으로 치환되기 때문이다. OFS의 기본값은 스페이스라서 콤마 대신 스페이스가 출력되었다.

 

 $ cat file
Hello 1  
Hi 2      
Haha 3 

$ awk '$2 > 1' file
hi 2
haha 3

조건 표현식 $2 > 1이 참인 줄만 출력한다. 즉 두 번째 필드($2)의 값이 1 보다 큰 줄만 출력한다.

 

 

 $ cat file
Hello 1  
Hi 2      
Haha 3 

$ awk '{ print $0 }' file
hello 1
hi 2
haha 3

$0은 필드를 나누지 않은 상태의 전체 레코드를 의미하는 내장변수이다. 즉 줄 내용 전체가 그대로 출력된다.

 

$ awk -F: {print $1} file    # 콜론(:) 을 필드 구분자로 사용

$ awk -F'[:,]' {print $1} file    # 콜론(:)과 콤마(,)를 필드 구분자로 사용
-F 옵션을 사용하여 필드 구분자를 직접 지정할 수도 있다.

 

printf
출력 포맷을 지정하고 싶을 때는 print 대신 printf 함수를 사용한다. 사용법은 C언어의 printf와 유사하다.
printf는 print와 달리 개행(new line)처리가 되지 않으므로, 필요시 \n을 직접 명시한다.


문자 설명
%c character
%s string
%d, %ld 10진수, long 10진수
%u, %lu unsigned 10진수
%x, %lx 16진수
%o, %lo 8진수
%e 부동소수점, e-표기법
%f 부동소수점
%g 부동소수점. %e와 %f 중 적은 자릿수를 차지하는 표기법을 사용.

 

 $ cat file
Hello 1  
Hi 2      
Haha 3 

$ awk '{ printf "word is %-10s and number is %8d and %03d\n", $1, $2, $2}' file
word is hello      and number is        1 and 001
word is hi         and number is        2 and 002
word is haha       and number is        3 and 003

%-10s : 10자리의 공간에 string 출력. 대시-는 왼쪽 정렬을 의미.
%8d : 8자리의 공간에 10진수 출력. 기본으로 오른쪽 정렬.
%03d : 3자리의 공간에 10진수 출력. 남는 공간은 0으로 채움.


내장변수

위에서 언급한 FS, OFS 외에도 여러 내장변수가 존재한다.

내장변수의 이름은 대문자로 이루어져 있다.
내장변수는 패턴 및 command 내에서 사용할 수 있으며 값을 재설정 할 수도 있다.


이름 설명

ARGC       : 커맨드라인 매개변수의 갯수
ARGV       : 커맨드라인 매개변수의 배열
FILENAME : 입력 파일의 이름
FNR         : 현재 파일의 레코드 갯수
NF           : 현재 레코드의 필드 갯수
NR           : 레코드 번호
OFMT       : 숫자를 위한 출력 포맷
OFS         : 출력 필드 구분자
ORS         : 출력 레코드 구분자
RS           : 입력 레코드 구분자
RLENGTH  : match 연산자로 매칭된 부분의 길이
RSTART    : match 연산자로 매칭된 부분의 시작 위치
SUBSEP     : 배열 구분자


 

NR, NF

$ cat file
hello 1
hi 2
haha 3

$ awk '/haha/{ print NR, $1, NF }' file
3 haha 2

NR은 파일 내에서 해당 레코드의 번호를 나타내는 내장변수이다. NF은 해당 줄의 필드 갯수를 나타내는 내장변수이다.

 

OFMT
$ awk `{ OFMT="%.2f"; print 1.234567, 12E-2; }` file
OFMT는 print 함수의 출력 포맷을 지정하는 내장변수이다.

 

ARGV, ARGC
ARGV는 shell 커맨드라인에서 입력받은 매개변수가 순서대로 저장되는 내장 배열이다. nawk 에서만 지원한다.
nawk라는 명령어 자체도 매개변수에 포함되며(ARGV[0]), 명령어의 옵션들은 포함되지 않는다.
ARGC는 커맨드라인 매개변수의 갯수가 저장되는 내장 변수이다.
$ nawk -F',' '{ for(i=0; i<ARGC; i++){ print ARGV[i]; } }' filename1 filename2
nawk        # ARGV[0]
filename1   # ARGV[1]
filename2   # ARGV[2]

match 연산자 (~, tilde)
특정 필드의 값이 정규표현식에 매칭되는지 검사할 때는 ~를 사용한다. 매칭되지 않는지 검사할 때는 !~를 사용한다.

$ awk '$1 ~ /[Hh]ello/' file    # 첫 번째 필드가 Hello, hello인 레코드를 출력
$ awk '$1 !~ /^hello/{ print $1 }' file

variable
정수, 부동소수점 실수, 문자열 등을 위한 변수를 사용할 수 있다.
awk의 변수는 선언 없이 바로 사용할 수 있으며, 사용되는 형태에 따라 0이나 ““으로 초기화된다.
awk 내에서의 변수는 shell에서의 변수와 기본적으로 호환되지 않는다.

shell의 변수를 awk로 전달하기 위해서는 -v 옵션을 사용할 수 있다.

-v 옵션
-v 옵션을 통해 전달된 변수는 awk의 BEGIN 문에서 사용할 수 있다,

BEGIN
awk가 입력 파일을 처리하기 전에, 수행해야 될 전처리 동작들을 지정할 수 있다.
OFS, RS, FS 등 내장변수의 값을 변경하거나, 사용자 정의 변수의 초기화 등을 하기 위해 쓰인다.

 

  $ cat file
Hello 1  
Hi 2      
Haha 3 

 $ awk 'BEGIN{ FS=":"; OFS="\t"; } {print $1,$2 }' file
hello 1
hi 2
haha 3
$ awk 'BEGIN{ print "Hello, world!" }

BEGIN 블럭은 awk가 입력 파일을 열기 전에 수행되므로, 입력 파일 없이 BEGIN 블럭만 실행할 수도 있다.


END
입력 파일의 모든 줄의 처리가 끝난 후에, 맨 마지막으로 실행할 동작들을 지정할 수 있다.
$ awk '{print $1} END{ print "process done."; }' file
$ awk 'BEGIN{ sum = 0; } /hello/{ sum += $1; } END{ print "sum is "sum; }' file
이렇게 BEGIN, 패턴, command, END 를 모두 함께 사용할 수 있다.

 

Array in awk
awk의 배열은 연관 배열(associative array)로, key와 value를 갖는 Hash Set 이다.
변수와 마찬가지로, 미리 선언하지 않아도 바로 사용할 수 있다. (사용과 동시에 생성된다.)
배열이 사용되는 타입에 따라 0이나 빈 문자열로 적당히 초기화된다.
배열의 순회
for (item in array) {
 print array[item];
}


delete
내장 함수 delete는 배열 요소를 삭제하는데 사용한다. - delete(array[item]);

$ awk '{ arr[x++] = $2; } END{ for(i in arr){ delete(arr[i]); } }' filename
기타 내장함수

sub
정규표현식에 매칭되는 부분을 지정한 문자열로 치환한다. longest 매칭이며, 레코드 내에서 여러번 매칭되어도 맨 왼쪽의 일치하는 부분에 대해서 한번만 치환한다. 치환할 대상을 지정하지 않으면 현재 레코드 전체($0)에 대해서 치환한다.

sub(/정규표현식/, “치환할 문자열”, “치환할 대상”);
sub(/정규표현식/, “치환할 문자열”); - $0 에 대해서 치환

gsub
sub와 유사하나 레코드 내에서 정규표현식이 매칭될 때마다 치환한다.

 

index
문자열 내에서 찾는 문자열이 나타나는 위치를 리턴한다. 위치는 1부터 시작하여 계산된다. - index(“문자열”, “찾는 문자열”);

 

length
문자열의 길이(문자 수)를 구한다.

length(“문자열”)
length 문자열을 지정하지 않으면 현재 레코드 전체($0)에 대한 길이를 구한다.


substr
문자열 내에서 지정한 위치부터의 부분 문자열을 반환한다.

substr(문자열, 시작 위치);
substr(문자열, 시작 위치, 문자열 길이)


match
문자열 내에서 주어진 정규표현식에 매칭되는 패턴이 있으면 시작 위치를 반환하고, 없으면 0을 리턴한다. 추가적으로 문자열이 매칭될 경우, 패턴의 시작 위치를 내장변수 RSTART에 저장하고 부분 문자열의 길이는 RLENGTH에 저장한다. 이는 match 함수로 매칭 여부를 확인 후 substr을 사용하는데 유용하다. 단 nawk에서만 동작한다.

match(“문자열”, /정규표현식/);


split
문자열을 단어 단위로 나누어 배열에 저장한다. 필드 구분자를 지정하지 않으면, 내장변수 FS의 값이 디폴트로 사용된다.

split(문자열, 저장할 배열, 필드 구분자);
split(문자열, 저장할 배열); - 내장변수 FS의 값을 필드 구분자로 사용
$ awk 'BEGIN{ split("05/01/2016", date, "/"); print date[3]; }'
2016

int
소숫점 이하를 버리고 정수부만 반환한다.

int(x)

rand
0~1 사이의 난수를 반환한다.

rand()

 

 

반응형
반응형

Grep의 사용방법에 대해서 알아보는 시간을 갖도록 하겠습니다.

 

grep은 리눅스/유닉스 환경에서 문자열을 파싱할 수 있는 명령어 입니다. 이것을 잘활용하면 많은 효과를 볼 수 있는데 이에 대해 알아보는 시간을 갖도록 하겠습니다.

 

기본 옵션

1. -n : 파일 안에서의 패턴에 발견된 라인 및 라인 번호

2. -v : 패턴이 발견되지 않은 라인을 출력

3. -i : 대소문자 무시 (ignore)

4. -l : 패턴이 들어 있는 파일 이름만 출력

5. -c : 패턴이 들어있는 라인 번호의 개수

 

<옵션 분석>

1. grep 

root@ubuntu:~# grep root /etc/group
root:x:0:

2. grep -v : 해당 패턴을 제외한 결과 행을 출력

root@ubuntu:~# grep -v root /etc/group
daemon:x:1:
bin:x:2:
sys:x:3:

 

3. grep -c : 해당 패턴이 들어간 행의 개수를 카운트하여 출력
root@ubuntu:~# grep -c root /etc/group
1

4. grep -l : 해당 패턴을 대상 파일에 존재하는지를 판단하고 존재한다면 대상 파일명을 출력

root@ubuntu:~# grep -l root /etc/group /etc/hosts /etc/passwd
/etc/group
/etc/passwd

5. grep -i :  대소문자를 구별하지 않고 패턴에 해당하는 문자가 포함된 행을 출력

root@ubuntu:/shell# grep -i boy sample.txt
I am a boy
Boy have a robot

<특수문자>

1. 사각괄호 ([ ]) : [ ] 안에 들어 있는 검색을 모두 수행한다.

2. 마침표 ( . ) : 한 문자를 대신한다. 대신한 문자는 모든 문자로 간주 검색을 한다.

3. 괄호안의 대시 ( [ - ] ) :  - 괄호 안의 무자 잡합의 문자 범위를 지정한다.

4. 탈자기호 ( [ ^ ] ) : ^ 특정 조건에 속하지 않은 문자열을 출력한다.

5. 별표 ( * ) : * 지정한 문자열이 0, 1 , 수 차례 반복된다는 의미

6. 행시작(^)끝($) : ^ 괄호 밖의 탈자기호는 행 시작부만 검색한다는 의미이고 $는 지정한 문자열로 끝나는 행만 검색

 

<특수문자 활용>

1. 사각괄호 ([ ]) : [ ]안의 안의 문자집합을 모두 검색해 출력한다.

root@ubuntu:/shell# grep [bg] sample.txt
I am a boy
Boy have a robot
Robot is a blue
You are a girl
root@ubuntu:/shell# grep [BG] sample.txt
Boy have a robot
Girl have a doll

 

2. - 의 사용

root@ubuntu:/shell# grep [a-z]oy sample.txt
I am a boy
root@ubuntu:/shell# grep [a-z]irl sample.txt
You are a girl
root@ubuntu:/shell# grep [A-Z]irl sample.txt
Girl have a doll
root@ubuntu:/shell# grep [A-Z]oy sample.txt
Boy have a robot
root@ubuntu:/shell# grep [A-Za-z]oy sample.txt
I am a boy
Boy have a robot

 

3. . 의 사용 : . 은 한 문자를 대신하여 그에 속한 모든 문자(공백 포함)를 출력

root@ubuntu:/shell# grep b.y sample.txt
I am a boy
root@ubuntu:/shell# grep b.. sample.txt
I am a boy
Boy have a robot
Robot is a blue
root@ubuntu:/shell# grep b... sample.txt
Robot is a blue
root@ubuntu:/shell# grep b.... sample.txt
Robot is a blue
root@ubuntu:/shell# grep b.... sample.txt

4. [ ] 안의 ^의 사용 : 이것은 혼자 쓰이는 ^와는 다르다. ^은 포함하지 않는 문자열을 검색

root@ubuntu:/shell# grep b[^o]y sample.txt
root@ubuntu:/shell# grep b[^a]y sample.txt
I am a boy
root@ubuntu:/shell# grep [^b]oy sample.txt
Boy have a robot

 

5. *의 사용 : *은 반복을 나타내는 연산 중 하나이다. 파일 검색과는 조금 다르니 혼단하지 말았으면 합니다. 정규연산식에서 *은 지정한 문자열이 반복되는 반복되지 않든 모두 검색하라는 것이다.

root@ubuntu:/shell# grep b*oy sample.txt
I am a boy
Boy have a robot
root@ubuntu:/shell# grep bo*y sample.txt
I am a boy

6.  [ ] 밖의 ^사용 : ^는 지정한 검색 문자열로 시작하는 행만을 검색하여 반환합니다.

root@ubuntu:/shell# grep ^I sample.txt
I am a boy
root@ubuntu:/shell# grep ^B sample.txt
Boy have a robot
root@ubuntu:/shell# grep ^I sample.txt
I am a boy

 

7. $의 사용 : $는 지정한 검색 문자열로 끝나는 행만을 검색하여 반환

root@ubuntu:/shell# grep boy$ sample.txt
I am a boy
root@ubuntu:/shell# grep girl$ sample.txt
You are a girl


 

 

반응형
반응형

정규식에는 많은 규칙이 있지만... 실제로 사용해 보지 않으면 그 묘미를 확인하기가 어렵죠 지금부터는 정규식을 활용해서 실제로 해볼수 있는 여러가지 작업에 대해 소개해보도록 하겠습니다.

 

먼저 시작하기 전에

https://regexper.com/

 

이사이트에서는 자신이 입력한 정규식에 대한 검증을 시각화로 도와주는 사이트 입니다. 혹시 자신이 작성한 정규식을 검증해 볼 필요가 있을때 유용하게 사용할 수 있는 사이트이니 참고해 주시고...

 

1. 핸드폰 번호

사람들이 많이 사용하는 핸드폰 번호는

형식이 010-1234-5678 이런식으로 숫자 3자리 - 4자리 - 4자리로 구성되어 있죠

 

이런 경우에는

 

1) /^\d{4}-\d{5}-\d{5}$/

 

2) /^010\-[0-9]{4}\-[0-9]{4}$/

 

2가지 경우로 표현할 수 있습니다.

 

첫번째는 10진수의 숫자 3개와 4개, 4개를 표현하는 것입니다. 물론 자유도가 다소 높죠

두번째는 앞에 010이라는 전재를 하고 각 자리수별로 가능한 범위를 지정합니다. 이때는 사용자에 따라서 특정 핸드폰을 구별해서 처리하고 싶을 때 가능한 방법입니다.

 

 

2. IP 주소

 

아이피주소는 간단하지만 예외가 많습니다

 

단순하게 ###.###.###.### 이렇게 생각하고 작성할 수 도 있습니다.

하지만  ##.##.###.## 이 경우도 있고 . 다시 말해 아까 전과는 달리 자릿수가 변동이 생길수가 있죠. 자릿수를 무조건 3자리로 정한다면 이야기는 달리지겠지만요...

 

/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

 

정규식이 첫번째로 잡아낸 그룹은 실제로 매치된(captured)된 그룹이 아닙니다. 왜냐하면 ?: 가 그안에 위치하고 있기 때문입니다. ?:는 파서가 이 그룹을 잡아내지 않도록 합니다. 또한 이 잡히지 않는 그룹은 3번 반복되기를 원합니다.(그룹의 끝에 {3}) 이 그룹은 또다른 서브그룹과 점(.)을 담고 있고 파서는 점(.)이 뒤에 있는 서브그룹을 매치하려고 찾습니다.

서브그룹은 또다른 잡히지 않는(non-captured) 그룹입니다. 이것은 0~5가 뒤에 오는 "25"거나 0~4와 모든 숫자가 뒤에 오는 "2"이거나 옵션이 0 또는 2개의 숫자가 이어지는 숫자들의 문자셋의 묶음입니다.

이 3가지가 매치된 이후에 다음 캡쳐되지 않는 그룹으로 들어갑니다. 이것은 0~5가 이어지는 "25" 또는 0~4와 함께 오는 "2" 그리고 마지막에 다른 숫자(0이나 두자리 숫자)가 옵니다.

마지막 문자($)와 함께 이 복잡한 정규표현식이 끝납니다.

 

 

 

 3. URL

 

URL을 보는 방법에대해 알아보겠습니다.

 

URL을 수식으로 한번 풀어 보면

 

http[s]://XXXX.XXX/XXX 이런식으로 할 수가 있겠죠

 

 

/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w_\.-]*)*\/?$/

 

 

첫번째 그룹은 모두 옵션인데 이것은 URL이 "http://"나 "https://" 또는 둘다 없이 시작하도록 한다. s뒤에 물음표(?)는 URL이 http와 https를 모두 허용한다. 이 그룹전체를 선택사항으로 하기 위해서 뒤에 물음표(?)를 추가했습니다.

다음은 도메인명으로 한개이상의 숫자, 문자열, 점(.), 하이픈(-)뒤에 또다른 점(.)이 오고 그 뒤에 2~6개의 문자와 점이 옵니다. 이어지는 부분을 추가적인 파일과 디텍토리에 대한 부분으로 이 그룹에서는 갯수에 관계없이 슬래쉬(/), 문자, 숫자, 언더스코어(_), 스페이스, 점(.), 하이픈(-)이 나올 수 있으며 이 그룹은 많은 수의 디렉토리와 파일과 매치됩니다. 물음표(?)대신 별표(*)를 사용한 것은 별표는 0 또는 1이 아닌 0 또는 1개이상을 의미하기 때문입니다. 만약 물음표(?)를 사용했다면 오직 한개의 파일/디렉토리만 매치될 수 있었을 것입니다.

그 뒤에 슬래시(/) 매치되지만 이것은 선택사항이며 마지막으로 문자열의 끝($)이 나타납니다.

 

 

 

반응형
반응형

쉘 스크립트에서 문자열을 다루기 위해서는 awk, cut, grep의 기본 명령어만으로도 충분하지만, 보다 코드를 간결하게 작성하고 싶고 복잡한 미션을 수행하기 위해서는 정규표현식이 필요합니다.

 

물론, 제 생각에는 정규표현식은 필요악??? 이라고 생각되는 측면이 많이 있습니다. 일단 프로그램언어나 시스템 별로 차이점도 존재하고 쓰는 사람만다 다양한 방법으로 사용이 가능하고 제일 중요한 점은 가독성이 떨어지기 때문에 추후 유지보수 측면에서도 떨어지는 단점이 있습니다.

 

그렇지만 정규표현식은 감히 말하건데... MSG같은 마법으로 우리에게 다가오기 때문에 문자열 관련 측면이 아니더라도 알아두면 좋을거 같습니다.

 

표현식(expression)이란 문자 그대로의 의미 이상으로 해석되는 메타문자(metacharacters)라고 부르는 문자들의 집합을 말합니다.

 

예를 들어, 인용 부호(quote symbol)는 어떤 사람이 말한 것을 나타내 주기도 하지만 또한 그 뒤에 나오는 심볼에 대해서 메타적 의미를 부여하기도 합니다. 정규 표현식은 유닉스에 특별한 특징을 부여하는 문자들과 메타문자들의 집합입니다.

 

정규 표현식은 주로 텍스트 탐색과 문자열 조작에 쓰입니다. 정규 표현식은 하나의 문자와 일치(match)하거나, 혹은 문자열의 일부분(substring)이나 전체 문자열인 문자 집합들과 일치하게 됩니다.

 

<기초>

 

1. 별표(*)는 바로 앞의 문자열이나 정규 표현식에서 0개 이상 반복되는 문자를 나타냅니다.

"113*" 은 11 + 하나 이상의 3 + 가능한 다른 문자들 을 나타냅니다: 113, 1133, 11312, 기타 등등.

 

2. 점(.)은 뉴라인을 제외한 오직 한 개의 글자와 일치합니다.

"13." 은 13 + 빈칸을 포함한 최소 한 글자 를 나타냅니다: 1133, 11333, 하지만 13은 뒤에 한 글자가 빠져 있기 때문에 아닙니다.

 

3. 캐럿(^)은 줄의 시작을 나타내지만 가끔 문맥에 따라서는 정규 표현식에서 문자 집합의 의미를 반대로 해석해 줍니다.


4. 정규 표현식의 제일 끝에 나오는 달러 표시($)는 줄 끝과 일치합니다.

"^$" 는 빈 줄과 일치합니다.

 

5. 대괄호([...])는 단일 정규 표현식에서 표현하기 위해 문자들을 집합으로 묶어 줍니다.

"[xyz]" 는 x, y, z 중에 한 글자와 일치합니다.

"[c-n]" 는 c에서 n 사이에 들어 있는 한 문자와 일치합니다.

"[B-Pk-y]" 는 B에서 P까지 중이나 k에서 y까지 중의 한 글자와 일치합니다.

"[a-z0-9]" 는 소문자나 숫자중의 한 문자와 일치합니다.

"[^b-d]" 는 b에서 d사이의 문자를 제외한 모든 문자를 나타냅니다. ^은 바로 뒤에 나오는 정규 표현식의 의미를 반대로 해석하게 해 줍니다(다른 문맥에서 !의 의미와 비슷함).

여러개의 대괄호로 묶인 문자들은 일반적인 낱말 패턴을 나타냅니다. "[Yy][Ee][Ss]"는 yes, Yes, YES, yEs, 등등을 나타냅니다. "[0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]"는 주민등록번호와 일치합니다.

 

6. 역슬래쉬(\)는 특수 문자를 원래의 문자 의미대로 해석하게 해줍니다(escape).

"\$" 는 정규 표현식에서 줄 끝(end-of-line)을 나타내는 의미대신 "$" 문자 그대로 해석하게 해줍니다. 비슷하게 "\\"는 그냥 "\" 문자 그 자체를 나타냅니다.

 

 

<메타 문자 정리>

 

1) ^ : 문자열의 처음을 나타냄

맞는 문자열
^group group으로 시작하는 문자열 group, groups, group program, …

 

2) $ : 문자열의 끝을 나타냄

맞는 문자열
ing$ ing로 끝나는 문자열 ing, sing, hosting, booting, …
^code$ code로 시작하고 끝남 code

3) . : 임의의 한문자를 나타냄

맞는 문자열
a.b a와 b 사이에 한 문자가 낀 문자열 aab, abb, acb, …
ab. ab 다음에 한 문자가 붙은 문자열 aba, abb, abc, …
a..b a와 b 사이에 두 문자가 낀 문자열 a11a, aabb, abbb, …
^.ape ape 앞에 한 문자가 낀 문자열로 시작함 tape, caper, …


 

4) * : 바로앞의 문자가 없거나 하나 이상이 있는 겅유

맞는 문자열
m*r r 앞에 m이 없거나 하나 이상 있음 r, mr, mmr, mmmr, …
mr*s m 다음에 r이 없거나 하나 이상 있고 s가 맨 뒤에 있음 ms, mrs, mrrs, mrrrs, …
mrs* mr 다음에 s가 없거나 하나 이상 있음 mr, mrs, mrss, mrsss, …
5) + : 바로 앞의 문자가 하나 이상 있음
맞는 문자열
m+r r 앞에 m이 하나 이상 있음 mr, mmr, mmmr, …
mr+s m 다음에 r이 하나 이상 있고 s가 맨 뒤에 있음 mrs, mrrs, mrrrs, …
mrs+ mr 다음에 s가 하나 이상 있음 mrs, mrss, mrsss, …
6) ? : 앞의 문자가 없거나 하나임

 

맞는 문자열
m+r r 앞에 m이 하나 이상 있음 mr, mmr, mmmr, …
mr+s m 다음에 r이 하나 이상 있고 s가 맨 뒤에 있음 mrs, mrrs, mrrrs, …
mrs+ mr 다음에 s가 하나 이상 있음 mrs, mrss, mrsss, …
7) [] (꺽쇠묶음, 대괄호):

  - 꺼꾀묶음은 한 문자를 가리킴

  - 묶음안의 내용은 가리키는 문자의 범위를 나타냄

    (문자 클래스로서 정규 표현식과는 언어가 다름)

  - 특정한 문자열을 제외하려면 묶음안에 '^'를 사용

맞는 문자열
[w]s s 앞에 w가 붙음 ws
[ws]p p 앞에 w나 s가 붙음 wp, sp
[a-z]8 8 앞에 잔 로마자(소문자) 하나가 붙음 a8, b8, c8, … , z8
[a-zA-z][0-9] 로마자 하나 뒤에 숫자 하나가 붙음 a0, b5, K3, …
[^w]s s 바로 앞에 w가 아닌 문자 하나가 붙음 as, 2s, es, …
[^ws]p p 바로 앞에 w나 s가 아닌 문자 하나가 붙음 ap, hp, op, …
[^a-z]8 8 바로 앞에 잔 로마자가 아닌 문자 하나가 붙음 A8, C8, 38, #8, …
^[^gh][^ij]$ g나 h가 아닌 한 문자로 시작하고  i나 j가 아닌 한 문자로 끝남
(꺾쇠묶음 밖의 ^는 문자열의 처음을 나타냄)
ab, ty, ig, jh, …

8) { } : 중괄호

  - 중괄호는 앞에 있는 문자의 개수를 나타냄

  - 묶음안에서 ' , '는  문자 개수의 범위를 나타낼때 씀

맞는 문자열
w{0}s s 앞에 w가 없음 s
w{1}s s 앞에 w가 하나 붙음 ws
ws{3}p w가 앞에 오고 s가 셋 붙으면서 p가 뒤에 붙음 wsssp
w{1,3}s s 앞에 w가 1~3개 붙음 ws, wws, wwws
w{,2}s s 앞에 w가 두 개 이하 붙음 s, ws, wws
w{2,}s s 앞에 w가 두 개 이상 붙음 wss, wsss, …

9) | : 또는 / or와 같은 선택문에 사용

맞는 문자열
word|phrase word 또는 phrase word, phrase
mount(ed|ing) mounted 또는 mounting mounted, mounting
[^(a|b|c)].+ a 또는 b 또는 c로 시작하지 않는 문자열  

10) \(거꿀빗금) : 메터문자의 성분을 없앨때 사용

맞는 문자열 안 맞는 문자열
\[[^\[\]]+\] 꺾쇠묶음으로 한 겹만 싸인 문자열 [a], [ab], [abc], … [], [[abcd]], [a[]], …
[^\.]+\.(com|net) com, net로 끝나는 바탕 도메인 이름
(서브 도메인이 아닌 것)
a.com, b.net, … b.a.com, .a.com, .net …

반응형
반응형

리눅스 시스템을 사용하게 되면 필연적으로 문자열을 처리해야 되는 상황이 있습니다. 그 상황에 대비하여 기초적인 단계부터 심화 단계까지 한번 살펴보는 시간을 갔다록 하겠습니다.

 

우선 처음으로는 간단한 명령어로 문자열을 파싱하는 그렇지만 아주 강력한 문자열을 다루는 방법을 알아보도록 하겠습니다.

 

어쩌면 지금 소개하는 방법은 문자열을 다루는 기초이자 핵심임을 알아 두셨으면 합니다.

 

먼저 grep은 해당 열에 찾고 싶은 문자열이 있는지를 찾는 명령어 입니다.

 

<sample.txt>

root@ubuntu:/shell# cat sample.txt
I am a boy
I am a girl

<grep.sh>

root@ubuntu:/shell# cat grep.sh
#!/bin/bash

cat $1 |grep boy

root@ubuntu:/shell# ./grep.sh sample.txt
I am a boy

보시는 바와 같이 grep을 사용하면 boy가 있는 문자열을 찾게 됩니다.

 

다음은 cut입니다. cut을 활용하게 되면 구분자(char)를 이용하여 문자열을 추출하게 됩니다. 다시말하면 열로서 구분을 한다는 의미입니다. 여기서 중요한 점은 구분자 한글자이여야만 됩니다. 예를 들면 csv 파일 같은 형식에 적합하겠습니다.

 

<sample.csv>

root@ubuntu:/shell# cat sample.csv
name,category,score
choi,math,90
park,english,80
kim,korean,100

<cut.sh>

root@ubuntu:/shell# cat cut.sh
#!/bin/bash

cat $1 |cut -d',' -f1

root@ubuntu:/shell# ./cut.sh sample.csv
name
choi
park
kim

 

마지막으로는 awk 입니다. cut과는 다르게 파라미터 단위로 파싱을 하게 됩니다. 예제 파일을 통해 확인 해보겠습니다

<sample1.csv>

root@ubuntu:/shell# cat sample1.csv
name       category               score
choi   math             90
park         english           80
kim    korean          100

<cut.sh>

root@ubuntu:/shell# cat awk.sh
#!/bin/bash

cat $1 |awk '{print $1}'

root@ubuntu:/shell# ./awk.sh sample.csv
name
choi
park
kim

보시는 바와 같이 불규칙한 공백이 있는 파일에서 공백을 기준으로 파라미터화 해서 원하는 출력을 뽑아내는 모습을 확인 할 수 있습니다.

 

반응형
반응형

함수를 활용해서 쉘스크립트안에서 멀티 스레드와 백그라운드를 구현하는 방법에 대해 알아보도록 하겠습니다. 사실 제가 쉘 스크립트를 사용하면서 다른 언어와 비교했을 때 가장 편하다고 생각했던 부분입니다.

 

리눅스에서는 command 뒤에 '&'를 붙이게 되면 백그라운드로 동작하게 되고 리눅스의 예약어 $!로 해당 PID 값을 갖고 있게 되면 그 프로세스를 제어할 수 있습니다. 일단 샘플 코드와 수행 결과 값을 확인해 보겠습니다.

 

 #!/bin/bash

THREAD()
{
        while [ 1 ]
        do
                echo "THREAD 1 : $1"
                sleep 1
        done
}

 

echo "CALL 1st thread - Background Operating"
THREAD first&
THREAD_1st_PID=$!


echo "THREAD PID : $THREAD_1st_PID"
sleep 5
echo "Wait 5sec -> 1st thread suspend 5sec  "
echo "CALL 2nd thread - Background Operating"
kill -19 $THREAD_1st_PID
THREAD second&
THREAD_2nd_PID=$!

sleep 5


echo "Wait 5sec -> 1st thread continue 5sec  "
kill -18 $THREAD_1st_PID
sleep 5
kill -9 $THREAD_1st_PID $THREAD_2nd_PID

 root@ubuntu:/shell# ./multi.sh
CALL 1st thread - Background Operating
THREAD PID : 13595
THREAD 1 : first
THREAD 1 : first
THREAD 1 : first
THREAD 1 : first
THREAD 1 : first
Wait 5sec -> 1st thread suspend 5sec
CALL 2nd thread - Background Operating
THREAD 1 : second
THREAD 1 : second
THREAD 1 : second
THREAD 1 : second
THREAD 1 : second
Wait 5sec -> 1st thread continue 5sec
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second

 

파란색으로 및줄친 부분이 백그라운드 및 멀티스레드의 핵심적인 요소 입니다. 해당 구문에 백그라운드로 돌리고 해당 프로세스의 PID값을 저장하고 순차적으로 하나의 스레드를 추가로 생성하고 마지막에는 스레드를 종료하고 마치게 되는 구조 입니다.

반응형

+ Recent posts