정규표현식 활용 - 태그는 무시하고 본문에 있는 영어단어만 찾기

Tip&Tech 2016.06.11 15:26

내용 보충


1. Sigil 0.9.8에서 문자열+ 형식이 문자열++로 해야 찾아집니다. 

예를 들어 이전에는 \d+ 로 1,12,123,1234,12345....를 찾을 수 있었는데 \d++로 해야 제대로 찾아지네요. Sigil 오류인지 이렇게 수정된건지 모르겠어요. 아래에서 +가 하나 붙은 식이 문제가 생긴다면 ++로 수정해 보세요.


2. 식을 조금 업그레이드 했습니다. 전자책을 사랑하는 사람들 모임(http://cafe.naver.com/ebookpublisher) 부씽님의 식을 보고 조금 수정했어요.


찾기 : \b(?<=[가-힣])([\w\s]++)

바꾸기 : <sub>\1</sub>


이 식으로 한글abc한글, 한글abc abc한글, 한글abc abc abc한글.... 의 패턴을 모두 찾을 수 있습니다. 

이 식의 문제는 한글abc 한글 처럼 영문표기 뒤에 한글이 바로 붙지 않으면 공백까지 포함시킵니다. 이 부분도 해결해 보겠습니다 ^^



<p class="ddf">가나다 abc 입니다</p>
영문 단어만 찾아서 변경하고 싶었습니다. 특정 단어같은 패턴이 없어서 본문 내용에서만 찾고 싶었는데 영어는 태그를 구분하지 않고 검색하는것 같아서 아쉽더라고요.


골드님이 주신 질문입니다.

Sigil 에서 정규표현식을 이용하다 보면 원하지 않는 값까지 찾게 되는 경우가 있습니다.

한자나 한글은 조금 덜한 편인데 영문이나 숫자를 찾을 때 이런 문제가 자주 발생하지요.


예를 하나 들어보겠습니다.


스티브 잡스Steven Paul Jobs는 애니메이션 영화 《인크레더블The Incredibles》과 《토이 스토리Toy Story》 등을 제작한 컴퓨터 애니메이션 제작사인 픽사의 소유주이자 CEO였다.


이 문장을 정규표현식으로 찾아 스티브 잡스, 인크레더블, 토이스토리 뒤에 붙은 영문에만 스타일을 주고 싶다면 어떻게 해야 할까요?


먼저 정규표현식으로 영어 단어를 찾아보겠습니다. Sigil 찾기 창에서 정규표현식을 선택한 후 ([a-zA-Z]+) 를 입력합니다. 한 단어씩 찾기 위해 +를 추가했습니다. 그리고 찾기 버튼을 누르면 어떻게 될까요?


<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"

"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title></title>

</head>

<body>

<p>스티브 잡스Steven Paul Jobs는 애니메이션 영화 《인크레더블The Incredibles》과 《토이 스토리Toy Story》 등을 제작한 컴퓨터 애니메이션 제작사인 픽사의 소유주이자 CEO였다.</p>

</body>

</html>


EPUB의 본문은 HTML로 되어 있어 본문의 단어를 찾기 전에 HTML 코드에 있는 xml이라는 영어를 먼저 찾아줍니다. 다음 찾기를 아무리 눌러 봐야 HTML에 영문이 너무 많아서 수작업으로 하는 것 보다 효율이 나지 않습니다.


이런 문제를 해결하려면 정규표현식을 사용하기 전에 무슨 목적으로 사용하느냐를 본인이 정확히 알아야 합니다.

이런것도 모르고 할 사람이 있을까 싶겠지만, 많은 사람들이 자신이 원하는게 뭔지 모르는 상태에서 막연한 개념만 갖고 시작하는 경우가 많습니다. 그러면 식을 세울 수가 없게 되지요.


전자책을 편집할 때 영어 단어를 찾아야 하는 이유가 뭐가 있을지를 먼저 생각해 보겠습니다.

제가 전자책을 만들면서 언제 정규표현식을 쓰는지를 정리하고,  각각의 상황에 맞는 식을 하나식 설명드리겠습니다.


저는 아래와 같은 이유로 정규표현식을 많이 사용합니다.


윗첨자 패턴의 영문, 한자, 일본어 단어에 스타일을 적용해야 할 때


주로, 단어 뒤에 붙은 설명을 윗첨자 형태로 스타일을 적용해야 할 때 많이 이용합니다. 


스티브 잡스Steven Paul Jobs

인크레더블The Incredibles

논어論語


책을 편집하다 보면 이런 편집을 많이 사용합니다. 책 한권에 수백개 이상 들어있는 윗첨자를 하나씩 찾아내 수정하려면 시간이 오래 걸리기 때문에 정규표현식을 사용합니다.


이런 편집에는 '패턴'이 있습니다. 이 패턴을 찾는게 정규표현식을 세우는데 가장 중요합니다.


예로 든 텍스트들은 전자책으로 편집하기 전에는 윗첨자가 적용돼 있지 않습니다. 그렇기 때문에 윗첨자는 패턴이 될 수 없습니다.


스티브 잡스Steven Paul Jobs


이 문장에서 찾을 수 있는 가장 확실한 패턴은 한글영어단어, 한글한자, 한글일본어 등 한글 뒤에 바로 단어가 온다는 점입니다. 윗첨자 형으로 설명이 들어간 단어는 괄호 같은 구분기호를 붙이든, 구분기호 없이 바로 단어를 붙이든 한글에 붙어 영문이나 한자가 나오는게 일반적입니다.


한글영문 패턴은 책을 편집할때 많이 나오지 않습니다. 윗첨자 설명 같은 특수한 경우가 아닌 이상 한글과 영문은 띄어쓰도록 되어 있습니다. 그래서 한글영문은 정규표현식으로 사용하기 좋습니다. 그렇다고 본문의 모든 윗첨자만 이 패턴이 적용되고, 다른 내용에는 이런 패턴이 없다는 보장은 할 수 없으니 편집자가 책의 내용에 따라 패턴을 확인할 필요는 있습니다.


한글영문 패턴일 때는 이런 식을 쓸 수 있습니다.



([가-힉]+)([a-zA-Z]+)



스티브 잡스Steven Paul Jobs


그런데 결과가 이상하지요? 찾기를 원하는건 영문인데 선택은 한글 단어와 영문이 함께 됩니다. 


여기서 다시 '목적'을 생각해야 합니다. 만약, 영문 단어를 확인하려는 목적이라면 이렇게 선택된다 해도 아무 문제 없습니다. 눈으로 확인하면 되니까요. 그런데 영문 단어에만 스타일을 적용하고 싶다면, 다시 말해 찾아바꾸기를 하고 싶다면 이렇게 선택되서는 곤란합니다.


정말 곤란할까요?


만약 아래와 같은 단어라면 전혀 곤란할 일이 없습니다.


잡스Jobs


이렇게 한글 단어 하나에 영문 단어 하나짜리라면 위에 설명한 식으로 찾아바꾸기가 가능합니다.


찾기 : ([가-힉]+)([a-zA-Z]+)

바꾸기 : \1<sup>\2</sup>


찾기와 바꾸기 영역에 이렇게 해보세요. 그러면 결과는 이렇게 나옵니다.


잡스<sup>Jobs</sup>


Sigil은 정규표현식으로 단어를 찾을 때 괄호를 하나의 묶음으로 처리합니다. (표현식1)(표현식2) 처럼 식을 괄호로 묶어 주면 바꾸기를 할 때는 \1, \2로 찾은 단어를 넣어줄 수 있습니다. 찾기 영역에서 (표현식1)이 찾은 단어는 바꾸기 영역에서 \1로, (표현식2)가 찾은 단어는 \2로, 표현식이 3, 4, 5개로 늘어나면 \3, \4, \5로 대치를 할 수 있습니다. 그렇기 때문에 한글abc으로 선택됐다 해도 abc에만 스타일을 적용할 수 있게 됩니다.


참고로, ([가-힉]+)를 ([가-힉])으로 바꿔도 이 식에서는 지장이 없습니다. 잡스Jobs를 찾든, 스Jobs를 찾든 결과는 동일하니까요.


이번에는 조금 더 확장을 해 보겠습니다.


스티브 잡스Steven Paul Jobs는

애니메이션Animation 제작사


이런 패턴 역시 한글영문 패턴입니다. 다만 한글영문, 한글영문 영문... 의 패턴이 되는거지요.


이런 형태는 조금 까다롭습니다. 패턴이 분명하다면 문제가 되지 않는데 패턴이 2개 이상으로 복잡해집니다. 먼저 '스티브 잡스Steven Paul Jobs는' 패턴을 비교하면 이렇습니다.


한글영문 공백 영문 공백 영문...... 영문한글


이런 패턴이라면 이렇게 처리할 수 있습니다.


([가-힉])([a-zA-Z].+?)([가-힉])


패턴의 중요한 포인트는 [한글영문....영문한글]입니다. 영문을 찾는 식에 물음포(?)를 넣어 준건 패턴을 너무 넗게 잡는걸 방지해주기 위해서입니다.


([a-zA-Z].+?)


이 식으로 찾은 영문단어에만 스타일을 지정하고 싶다면 바꾸기 영역에 아래처럼 넣어주면 됩니다.


\1<sup>\2</sup>\3


스티브 잡스<sup>Steven Paul Jobs</sup>는



그런데 이 식을 사용하면 '애니메이션Animation 제작사'가 문제가 됩니다. '《인크레더블The Incredibles》' 같은 패턴도 문제가 되고요.


애니메이션Animation 제작사


이 패턴은 \2가 대체하는 단어 영역이  'Animation '까지입니다. 공백이 포함되지요. 


《인크레더블The Incredibles》


여기서는 'The Incredibles》'까지 포함을 하게 됩니다. 


이런 문제를 해결할 방법이 아주 없는건 아닙니다. 하지만 식이 점점 복잡해지고, 식이 복잡해 지면 엉뚱한 결과가 나올 수 있습니다.


지금까지 설명도 상당히 복잡했는데 더 복잡해진다면 이 글도 보기 싫어지시겠지요^^?

그래서 제가 쓰는 아주 단순 무식한 방법이 하나 있습니다.

한번에 끝낼 수는 없지만 결과는 확실한 방법입니다.


먼저, 본문에 윗첨자가 달려야 하는 단어의 최대 갯수를 확인합니다. 인명이나 지명 같은 명사라면 많아야 4~5개 단어로 끝납니다. 만약 단어의 최대 갯수가 4개라면 아래 식을 반복합니다.


찾기 : ([가-힉])([a-zA-Z]+ [a-zA-Z]+ [a-zA-Z]+ [a-zA-Z]+)

바꾸기 : \1<sup>\2</sup>


찾기 : ([가-힉])([a-zA-Z]+ [a-zA-Z]+ [a-zA-Z]+)

바꾸기 : \1<sup>\2</sup>


찾기 : ([가-힉])([a-zA-Z]+ [a-zA-Z]+)

바꾸기 : \1<sup>\2</sup>


찾기 : ([가-힉])([a-zA-Z]+)

바꾸기 : \1<sup>\2</sup>


단순 무식한 방법이지만, 패턴을 단순화시켜 다양한 예외들을 모두 차단해 버렸습니다.

위 식의 패턴은 이렇습니다.


먼저 '한글영문1 영문2 영문3 영문4'을 찾습니다.


이 패턴은 한글영문, 한글영문1 영문2 패턴은 무시합니다. 만약 한글영문1 영문2 영문3 영문4 영문5라는 패턴이 있다면 문제가 됩니다. 그래서 가장 긴 영어단어 수를 확인해야 합니다. 


그 다음 영어단어를 하나씩 줄여가며 찾아줍니다. 


한글영문1 영문2 영문3은 영문4까지 있는 단어라면 문제가 되지만, 영문4까지 있는 단어는 이미 교체했기 때문에 영문3까지 있는 패턴에는 걸리지 않습니다. 영문2까지 있는 패턴 역시 영문3을 처리한 후라면 문제가 되지 않고요.


이 방식이 가능한 이유는, 대부분의 책이 윗첨자 설명을 문장 보다는 인명이나 지명 같은 단어를 처리하기 위해 사용하기 때문입니다. 그리고 인명이나 지명은 길어야 4~5단어 정도로 짧기 때문에 많아야 5번 내외로 반복해 주면 윗첨자형 설명은 모두 바꿀 수 있습니다.


본문 내에 있는 영어 단어만 찾아야 할 때도 있습니다.

윗첨자 같은 설명이 아닌, 본문 내의 영어 단어로, 한글과 다른 폰트를 적용하고 싶다면 '한글영문'이 아닌 '한글 영문' 형태의 패턴이 됩니다. 


이런 형태 역시 패턴을 먼저 찾는게 중요합니다.

본문 내에 쓰인 영문 단어라면 이런 패턴일 가능성이 높습니다.


한글 영문 한글

한글 영문1 영문2.... 한글


스티브 잡스는 Toy Story 등을 제작한 Computer Animation 제작사인 픽사의 소유주이자 CEO였다.


이런 패턴은 위의 식을 약간 수정해서 처리할 수 있습니다.


([가-힉]) ([a-zA-Z]+ [a-zA-Z]+ [a-zA-Z]+ [a-zA-Z]+...)


이런 패턴은 한글이 앞에 나오고, 한칸 공백을 띈 후 영문 단어가 여러개 나옵니다. 영문 단어 뒤에는 'CEO였다'cjfja 한글이 붙을 수도 있고, 'Toy Story 등을' 처럼 공백이 올 수도 있습니다.


공통되는 패턴은 한글+공백+영문, 영문이 몇개가 오든 시작은 이렇습니다. 그렇다면 윗첨자를 바꿀 때처럼 가장 긴 영어 단어 수에 맞춰 반복을 할 수 있습니다.




태그 사이에 영문만 들어있는 경우도 있습니다. 


위에 두 예는 한글이 들어있어 태그를 무시할 수 있었는데 태그와 태그 사이에 영문만 있을 경우에는 찾기 어렵습니다.

그럴 때는 태그 자체를 이용합니다. 


<p class="title">Toy Story</p>



(?sU)<p([^>]*>)



이 식은 <p...>태그를 찾아줍니다. <p> 태그 안에 어떤 클래스나 스타일, ID가 추가되든 상관 없습니다. 만약 <p class="title">...</p>로 묶인 영역을 <p>태그 대신 제목 태그인 <h2>로 바꾸고 싶다면 이 식을 활용할 수 있습니다.


찾기 : (?sU)<p([^>]*>)(.*)</p>

바꾸기 : <h2>\2</h2>


<p> 태그 안에 영문만 있는 문단을 찾고 싶다면 (.*) 부분을 수정해 주면 됩니다. ([a-zA-Z].+) 처럼요.

원하는 패턴에 맞게 식을 세워주면 다양하게 활용할 수 있습니다.



정규표현식을 제대로 활용하려면 두가지를 꼭 기억하세요.


1. 내가 찾고자 하는 내용의 패턴을 알아낸다. 이 패턴이 정규표현식이 됩니다.

2. 사용할 목적을 확실히 알고 있어야 한다. 찾아바꾸고 싶은지, 확인만 할건지, 전부 바꿀건지, 부분만 바꾸고 싶은지 등에 따라 식이 달라지고, 바꿀 영역에 들어갈 내용도 달라집니다.


이 두가지만 정확히 알고 있어야 정규표현식의 도움을 받을 수 있습니다.



설정

트랙백

댓글


티스토리 툴바