본문 바로가기

별걸다하는 IT/리눅스 유닉스

[리눅스/유닉스] 유용 명령어 sed를 살펴보자! sed 명령어 사용법과 예시, 패턴 스페이스와 홀드 스페이스, 유용 표현

[리눅스 유닉스 완전정복 목차]

안녕하세요.

주인장 양햄찌입니다.

오늘은 sed 명령어에 대해 살펴보려고 해요.

SED 명령어 알기, SED는 무슨 명령어야?

vi편집기 아시죵~ sed 명령어도 vi편집기처럼 편집에 특화된 명령어라고 생각하면 됩니다. 수정 치환 삭제 글추가 등 편집기 기능은 왠만한거 다 가능~!

근데 vi편집기는 편집기를 열어서 서로 소통하듯 수정/변경을 해나가는 대화형 방식이죠. 내가 커서로 라인도 옮겨다니면서.. 지우고 글쓰고 등등 마치 워드파일 수정하듯!

근데 sed는 명령행에서 파일을 인자로 받아 명령어를 통해 작업한 후 결과를 화면으로 확인하는 방식입니다.

마치 편집기를 명령어 쓰듯 사용하는 것과 같아요. 

sed 명령어를 이용해 파일을 변경했을 경우의 특징은, sed 편집기는 원본을 손상하지 않는다는 것입니다.

쉘 리다이렉션을 이용해 편집 결과를 저장하기 전까지는 파일에 아무런 변경도 가하지 않아요. 모든 결과는 내가 명령을 수행후 화면으로 출력되는데 출력된 결과가 원본과 다르더라도 원본에 손해가 없다는게 sed 명령어의 특징입니다.

 

sed 명령어는 streamlined editor를 의미합니다. streamlined는 '능률적인'을 의미하죠 ㅎㅎ

패턴 스페이스(Pattern space)와 홀드 스페이스(hold space)

sed 명령어는 동작시 내부적으로 두개의 워크스페이스를 사용하는데, (마치 우리 복붙할 때 임시 저장소 클립보드처럼~!) 이 두 버퍼를 패턴 스페이스(=패턴 버퍼)와 홀드 스페이스(=홀드 버퍼)라고 합니다.

이미지출처: https://code.snipcademy.com/tutorials/shell-scripting/sed/hold-buffer

패턴 버퍼는 sed가 파일을 라인단위로 읽을 때 그 읽힌 라인이 저장되는 임시 공간이예요.

우리가 sed명령어로 출력하라 하면 여기 있는 버퍼 내용을 출력하는거고, 뭔가 조작을 하면 여기 저장되어 있는 내용을 조작하는 겁니다. 원본을 건드는게 아니야~~ 즉 이 버퍼는 현재 내가 담고 있는 정보를 갖고 있겠죠. 텍스트 1라인에서 2라인으로 넘어가 글을 읽게 되면 여기 패턴 버퍼에는 2라인 현재 내용이 저장되겠죠. 

 

그럼 홀드 스페이스는, 홀드 버퍼는 뭐에 쓰일까요??

홀드 스페이스는 패턴 버퍼처럼 짧은 순간 임시 버퍼가 아니라 좀 더 길게 가지고 있는 저장소입니다. 2라인 작업중이더라도 1라인을 기억하고 있을 수 있는 거예요.

즉 어떤 내용을 홀드 스페이스에 저장하면,  sed가 다음 행을 읽더라도 나중에 내가 원할 때 불러와서 재사용할 수 있는 버퍼가 홀드 버퍼가 됩니다. 

준비사항: 테스트 파일 

명령어를 테스트 하기 위한 파일은 아래 포스팅에서 만들었던 employees 텍스트 파일을 사용했어요.

https://jhnyang.tistory.com/288

 

[SQL DEVELOPER] SQL 디벨로퍼 엑셀 익스포트 하는법, 텍스트파일로 내보내기, 엑셀 내보내기 설정, 컬

[ 데이터베이스 목차 바로가기 ] 안녕하세요ㅎㅎ 작업하다보면 가장 많이 필요한 일이 엑셀로 데이터 뽑는 건데요. 특히 회사업무에서 운영에 변경부분이 있다면 이를 기록해 작업내역을 남기��

jhnyang.tistory.com

텍스트 파일:

employees
0.00MB

vi편집기로 열어보면 안의 내용은 아래와 같음 

employees파일

sed 명령어 자주쓰는 대표적 사용법

아무래도 편집기 기능을 다 해주다보니 sed의 subcommand 즉, sed와 같이 쓰이는 명령어 조합이 굉장히 많은데요.

자세한 사용 예시들은 하단에 쭉 다루도록하고 대표적으로 자주 쓰이는 명령어 조합부터 일단 살펴보고 갑시다~! 

■ 특정 범위만큼 파일내용 출력하기 

1. sed -n '1p' employees;
2. sed -n '1,3p' employees;
3. sed -n '8,$p' employees;

여기서 p는 print의 약자로 출력을 의미합니다. 컴마는 주소 범위를 지정해요.

sed는 원본을 건드리지 않는다고 했죠! sed로 작업한 부분만 억제해서 출력시키고 싶다면 -n옵션을 써줘야해요.

그래서 -n옵션은 p와 항상 짝짝꿍으로 사용됩니다.

결과창

1. employees파일에서 첫 번째 행만 출력해서 화면에 보여준다.

2. employees파일에서 1~3라인 범위의 내용을 출력해서 보여준다.

3. employees파일에서 8라인부터 파일끝까지 출력해서 보여준다. $는 '끝'을 의미합니다. 

 

근데 3번과 같은 경우 앞에 헤더(EMPLOYEE_ID 이런 컬럼명) 가 없이 데이터값만 보이잖아요

1행이 헤더 데이터인데 8행부터 끝까지 출력했으니까~ 1행을 출력하고, 8행부터 끝까지 출력할 수 없을까?

sed -n -e '1p' -e '8,$p' employees

 여러개의 편집 명령을 실행할 때 -e 옵션을 씁니다. 다음에 오는 것도 편집 명령어라는걸 알려줘요.

첫 번째 행과 8~끝 행 두 부분을 출력해줍니다.

결과챵

 특정 단어로 시작하는 행들만 추출하기

보통 로그파일의 경우 데이터들의 구별하기 위해 unique한 값이 맨앞에 붙는 경우가 많죠 

한 예로, log20200527이라는 파일이 있는데 이 날짜에 처리된 거래들이 기록된다고 합시다.

그럼 그 거래를 구분하는 유니크값이 붙겠죠~? 상품코드라던가, 거래코드라던가 등등.. 도서관이면 대출기록에 도서거래일련번호가 로그에 찍히겠죠~~

1. sed -n '/^107/p' employees  -- 107로 시작
2. sed -n '/103/p' employees

107로 시작하는 행들을 뽑아줘~ 여기서 '^'는 메타문자로 '시작'을의미해요. 

그냥 특정 단어를 포함하고 있는 행들을 뽑을 때에는 ^메타 문자 없이 검색하면 됩니다.

107로 시작

이 외에도 여러 정규식을 포함하여 원하는 것들만 쏙쏙 골라서 추출하시면 돼용~

 

1. employees파일에서 107로 시작하는 행만 출력해서 화면에 보여준다.

2. employees파일에서 103을 포함하고 있는 행들을 출력해서 보여준다.

 파일에서 공백으로 이루어지거나 빈줄 제거하기 

1. sed '/^$/d' employees
2. sed '/^$/d' employees > new_employees
3. sed '/^ *$/d' employees > new_employees

1. employees파일에서 빈 라인들을 지운 후 내용을 출력해준다. 

2. employees파일에서 빈 라인들을 삭제한 후 결과를 new_employees라는 파일명으로 저장한다.

3. employees파일에서 빈 라인들이나 공백으로 채워진 행들을 삭제한 후 new_employees라는 파일명으로 저장한다.

 

여기서 보이는 'd' 서브명령어는 delete의 약자로 삭제를 의미합니다.

'/'사이에 들어있는 단어르 포함하고 있는 모든 줄을 삭제시키겠다! 를 의미하죠

그런데 ^는 행의 처음을 의미하고 $는 행의 끝을 의미하니까 행의 처음과 끝이 같이 만나있는 것 즉 빈 줄을 의미합니다~

employees 파일에서 빈 줄을 모드 제거하라 라는 뜻의 명령어가 되는거죠.

근데 1번처럼 하면 실제 원본 파일은 손상이 없기 때문에 제거 되지 않습니다. 2번처럼 redirection으로 new_employees파일을 따로 저장시켜주거나 '> employees'로 덮어쓰기해서 저장해줘야 완벽한 수정이 된다는거~

 

3번에 보이는 *는 메타문자로 앞의 문자를 0개 이상 찾습니다. 

행의 시작이 0개 이상의 공백으로 이뤄지다 끝을 맺는거니까 공백이거나 빈 줄을 찾아낸다는 의미가 되는것~

https://jhnyang.tistory.com/127

 

[리눅스 유닉스] 정규표현식 (Regular Expression) 메타문자 정리. vi편집기에서 정규표현식 응용해 검�

[리눅스 / 유닉스 목차] 안녕하세요! 지난 포스팅들에서는 정말 기본적인 vi 단축키에 대해서 알아봤는데요. 이번에는 알아두면 정말정말 유용한 vi 에디터 사용법 2편으로 찾아왔습니다. 검색에�

jhnyang.tistory.com

 단어 치환

IT_PROG라고 되어있는 부분을 DEVELOPER로 변경해봅시다.

1. sed 's/IT_PROG/DEVELOPER/g' employees
2. sed 's/IT_PROG/DEVELOPER/g' employees > new_employees
3. sed 's/it_prog/DEVELOPER/gi' employees > new_employees

s는 switch의 약자인가?? 치환할 떄 사용하는 subcommand예요.

여기서 s와 같이 쓰이는 g 플래그는 치환이 행에서 전체를 대상으로 이루어짐을 의미합니다. (걍 한 행에 바꿀게 여러개 있어도 다바꾼다는거, sed는 행by행이니까 g플래그를 쓰면 전체에서 뽑히는거 다 바꾼다는 뜻) 

즉 1번은 파일 전체에서 IT_PROG라는 단어를 찾아 DEVELOPER라는 단어로 변경해줘!

 

근데 이렇게 하면 실제 원본 파일이 변경된건 아니고 출력만 이렇게 보이는거예요.

vi employees해서 파일을 열어보면 DEVELOPER가 없음을 알 수 있습니다. 파일을 저장하기 위해 2번처럼 리다이렉션해주기!

3번에 보이는 i플래그는 변경 대상 단어를 찾을 때 대소문자를 무시한다는 플래그입니다.

SED subcommand 명령어 종류와 의미 

예시를 하나하나씩 살펴보면서 대표적인 subcommand들은 알아봤지만, 더 많은 subcommand들을 정리해보아요.

subcommand 의미
a\ 현재 행에 하나 이상의 새로운 행을 추가한다.
c\  현재 행의 내용을 새로운 내용으로 교체한다.
d 행을 삭제한다. 
i\ 현재 행의 위에 텍스트를 삽입한다. 
h 패턴 스페이스의 내용을 홀드 스페이스에 복사한다. 
H 패턴 스페이스의 내용을 홀드 스페이스에 추가한다.
g 홀드 스페이스의 내용을 패턴 스페이스에 복사한다. (패턴 스페이스가 비어있지 않은 경우에는 덮어쓰기~)
G 홀드 스페이스의 내용을 패턴 스페이스에 복사한다. (패턴 스페이스가 비어있지 않은 경우에는 그 뒤에 추가) 
l 출력되지 않는 특수문자를 명확하게 출력한다. 
p 행을 출력한다. 
n 다음 입력 행을 첫 번째 명령어가 아닌 다음 명령어에서 처리하게 한다. 
q sed를 종료한다.
r 파일로부터 행을 읽어온다.
! 선택된 행을 제외한 나머지 전체 행에 명령어를 적용한다.
s 문자열을 치환한다.

sed s와 같이 쓰는 치환플래그 

s와 쓰이는 플래그 의미
g 치환이 행 전체에 대해 이뤄진다.
p 행을 출력한다.
w 파일에 쓴다. 
x 홀드 버퍼와 패턴 스페이스의 내용을 서로 맞바꾼다. 
y 한 문자를 다른 문자로 변환한다. (y에 정규표현식 메타문자를 사용할 수 없다)

여기서 몇 개는 앞에서 살펴본 명령어들이죠?ㅎㅎ 

다양한 사용 사용 예시들 examples

1. 출력 p 명령어 예시

sed -n '/love/p' file

→ file파일에서 love가 포함된 행들을 찾아 출력으로 보여줘! (-n 옵션이 있어야 love 패턴을 포함하는 줄들만 출력합니다) 

sed -n '/west/,/east/p' file

file파일에서 west가 나오는 행과 east가 나오는 행 사이의 모든 행들이 출력됩니다. west가 east 다음에 나오면 west가 나오는 행부터 파일의 마지막까지 출력됩니다. 

sed -n '3,/^employee/p' file

 3번째 행부터 employee로 시작되는 행까지 출력합니다.

 

2. 삭제 d 명령어 예시

sed '3d' file

 file파일에서 3번째 행을 삭제합니다. 나머지 행들이 출력.

sed '5,$d' file

5번째 행부터 마지막 행까지 삭제, 그리고 나머지 행들이 출력된다. 

sed '$d' file

 마지막 행을 삭제. d명령어로 삭제된 행 이외의 모든 행들이 출력됨 

sed '/apple/d' file

 파일에서 apple 포함하는 모든 행을 삭제 나머지 행을 출력합니다.

 

3. 치환 s 명령어 예시

sed 's/clere/clear/g' file
sed -n 's/clere/clear/gp' file

→ g플래그는 치환이 행 전체를 대상으로 이뤄짐을 의미하죠. clere라는 단어가 보이면 clear로 치환해 보여달라는거

→ 이렇게 치환 s랑 -n,p조합이랑 같이 쓰면 변경이 일어난 행들만 출력해줍니다. 

cat file | sed 's/  */ /g'
sed -i 's/  */ /g' file

→ 뒤에 파일명 안붙이고 이렇게 어떤 명령의 결과를 input으로 쓰는 파이프라인과 함께 써도 좋습니다.

공백이 여러개가 왔을 때 하나의 공백으로 깔끔하게 치환해 출력해달라는 명령어! (원본 영향 없음) 

(GNU 리눅스) 이렇게 -i옵션을 사용하면 파일에 직접 수정을 가능케 합니다. (원본 영향 있음) 

sed 's/[0-9][0-9]$/&.5/' file

→ [0-9][0-9]는 두 자리 숫자를 의미하죠. 근데 그 다음에 끝을 의미하는'$'가 왔어요. 즉 '두 자리 숫자로 끝나는 행'이 바꿈의 대상이 됩니다. 여기서 '&'는 검색열에서 지정한 문자열을 대신합니다. 그 문자열 뒤에 '.5'가 붙었네요. 즉 두자리 숫자로 끝나는 행 (ex 94) 를 찾으면 뒤에 점오를 붙인 단어로 (ex 94.5) 치환해 보여달라는 명령어입니다.

 

4. 파일로부터 읽는(read) 명령어 r 예시 

sed '/ref/r addfile' file

→ file파일로부터 ref라는 단어를 찾으면 그 패턴찾은 행 뒤에 addfile의 내용을 붙여 출력합니다. 

Austin이라는 단어를 찾으면 addfile파일 내용을 읽어 그 패턴행 뒤에 더해 출력해줬어요.

5. 파일에다가 쓰는(write) w명령어 예시

sed -n '/north/w outputfile' file

→ file파일로부터 north라는 패턴이 포함된 행을 찾으면 그 선택한 행들을 outputfile에다가 저장합니다. 

 

6. 문자열 추가(append)하기 a\ 명령어 예시

sed '/END$/a\THANK YOU FOR READING' file

→ file파일에서 END로 끝나는 행을 찾아, 그 다음에 'THANK YOU FOR READING'을 추가합니다.

 

7. 패턴스페이스와 홀드스페이스 예시

sed -e '/northeast/h' -e '$G' file

→ file파일에서 northeast라는 단어를 찾은 후 그 행들을 홀드스페이스에 저장해놓습니다. (h명령어)

그리고 $는 마지막 행을 의미하니까 마지막 행에 홀드스페이스 내용을 패턴스페이스에 복사합니다. 대문자G의 경우 패턴스페이스에 내용이 있을 경우 뒤에 추가하는 명령어로, 텍스트 맨 뒤에 복사됩니다.

즉, 패턴 northeast를 포함하는 행들은 모두 홀드 스페이스로 복사되었다가 파일의 마지막에 추가됩니다.

 

오늘은 여기까지입니다. sed명령어가 워낙 사용방법이 다양하다보니 포스팅이 너무 길어졌네요.ㅎㅎㅎ 더 자세한 사용법은 man 명령어를 참고해주세요 

공감/댓글/광고보답은 정보공유에 큰 동기가 됩니다 :) 

다음 포스팅에서 또 봐요 !