2010년 8월 25일 수요일

[프로그래밍] ASP 문자열 관련 함수


 































문자열 관련 함수
1. UCASE, LCASE 문자열의 내용을 대문자, 소문자로 변환시켜준다.
2. LEN 문자열의 길이를 반환한다.
3. LEFT, RIGHT, MID 문자열의 좌, 우, 중간에서 지정한 만큼의 문자열을 뽑아낸다.
4. INSTR, INSTRREV 해당되는 문자열의 좌측, 우측 위치를 반환한다.
5. LTRIM, RTRIM, TRIM 문자열의 좌측, 우측, 전체의 공백을 제거한다.
6. REPLACE 문자열의 내용중 일부를 다른 문자열로 변경한다.
7. SPLIT 문자열에서 특정 문자열을 기준으로 나누어 배열로 저장한다.

오늘도 여전히 다룰게 많군요. (그래도 재밌는 함수들이 많이 있습니다. ^^)
그러면 이제부터 본격적으로 위에 언급한 함수들의 자세한 내용을 알아보도록 할까요?

1. UCASE, LCASE

UCASELCASE 함수는 각각 문자열을 '대문자', '소문자' 로 변환시켜 주는 함수입니다.
(UCASE 는 'uppercase (대문자)', LCASE 는 'lowercase (소문자)' 의 약자입니다.)
예를 들어 strTest 라는 변수에 "I Love You" 라는 문자열이 있다고 가정해 보겠습니다.

Dim strTest, strUpper, strLower

strTest = "I Love You"
strUpper = UCASE (strTest)
strLower = LCASE (strTest)

이런 경우 strUpper 변수에는 "I LOVE YOU" (대문자로 변환됨) 라는 문자열이,
그리고 strLower 변수에는 "i love you" (소문자로 변환됨) 라는 문자열이 들어가게 됩니다.
어떻습니까? 쉽게 이해를 하실 수 있으시겠지요.

그렇다면 대,소문자로 변환할 수 없는 한글이나 숫자를 입력하는 경우에는 어떻게 될까요?
똑똑한 ASP 는 대,소문자로 변환할 수 없는 경우에는 원본 문자열을 그대로 반환합니다.
즉, UCASE ("사랑해요") 또는 LCASE ("486486") 처럼 변환이 불가능한 문자열을 입력했다면 원본 문자열에 아무런 수정을 가하지 않고 그대로 돌려준다는 의미가 되는 것입니다.

2. LEN

LEN 은 길이를 의미하는 'length' 의 약자로서 '문자열의 길이' 를 반환합니다.
LEN 함수는 한글, 숫자, 영문, 특수 문자를 가리지 않고 한 글자당 1씩 계산하는데요.
주의하셔야 할 점은 '공백' 도 문자로 인식하여, 길이에 포함시킨다는 사실입니다.
예를 들어 strTest 라는 변수에 "I Love You..." 라는 문자열이 들어 있다고 해볼까요?

Dim strTest, intLength

strTest = "I Love You..."
intLength = LEN (strTest)

이 경우 intLength 에는 13이라는 정수형 값이 들어가게 되는 것이지요.
만약 strTest 라는 변수에 아무런 값도 들어있지 않거나, 빈 문자열이라면?
LEN 함수는 이러한 경우에 0 을 반환합니다. 해당 문자열의 길이가 없기 때문이지요.

3. LEFT, RIGHT, MID

LEFT (RIGHT) 함수는 문자열의 왼쪽 (오른쪽) 에서 지정한 길이 만큼의 문자열을 반환하고,
MID 함수는 문자열의 지정한 위치에서, 지정한 길이 만큼의 문자열을 반환합니다.
이 함수들에 대한 설명은 예를 들어 설명드리는 것이 가장 좋을 것 같네요.

Dim strTest, strLeft, strRight, strMid

strTest = "Welcome to Dukyoung.net"
strLeft = LEFT (strTest, 7)
strRight = RIGHT (strTest, 12)
strMid = MID (strTest, 4, 7)

자, 위와 같은 문장을 ASP 에서 실행하면, 각각의 변수에는 어떤 값들이 들어가게 될까요?
우선 strLeft 에는 strTest 의 왼쪽에서 7글자.. "Welcome" 이 들어가게 됩니다.
그리고 strRight 에는 strTest 의 오른쪽에서 12글자.. "Dukyoung.net" 이 들어가지요.
마지막으로 strMid 에는 strTest 의 (왼쪽에서) 4번째 글자인 c 부터의 7글자..
즉, "come to" 라는 문자열이 들어가게 됩니다. (공백도 하나의 문자로 인정합니다.)

사용법이 상당히 간단하지요? 잘 기억해 두시기를 바랍니다.

4. INSTR, INSTRREV

INSTRINSTRREV 함수는 '특정 문자열의 위치' 를 알아내는 함수입니다.
예를 들어서 "내가 그린 기린 그린 그림은 잘 그린 기린 그린 그림이다." 이라는 문장에서
'그린' 이라는 문자가 어디있는지 찾아내려면 다음과 같이 사용하시면 됩니다.

Dim strTest, intTest

strTest = "내가 그린 기린 그린 그림은 잘 그린 기린 그린 그림이다."
intTest = INSTR (strTest, "그린")

이 문장을 실행하고 난 다음 intTest 변수에 들어갈 값은 4가 됩니다.
즉, "그린" 이라는 문자는 strTest 문자열의 4번째 위치에 있다는 뜻이 되는 것이지요.
(만약 "그린" 이라는 문자열이 없다면 intTest 에는 0 이라는 값이 들어가게 됩니다.)
그런데.. INSTR 함수에서는 또 다른 옵션을 줄 수가 있는데요.
그것은 바로 '시작 위치' 를 지정할 수가 있다는 것입니다.
위의 예를 조금 변형하여 다음과 같이 수정을 해보겠습니다.

intTest = INSTR (5, strTest, "그린")

이 함수의 의미는 과연 무엇일까요?
이것은 "그린" 이라는 문자를 찾긴 찾는데.. 5번째 문자 이후부터 찾겠다는 뜻이 됩니다.
즉, 가장 앞에 있는 5 라는 인자는 '시작 위치' 를 나타내는 것이지요.
따라서 이 함수를 실행시킨 후 intTest 의 값은 4가 아닌 10이 됩니다. (두번째 '그린'의 위치)
(사실.. 이 함수에는 가장 마지막 인자로 이진(Binary), 텍스트(Text) 비교에 관련된 인자가
하나 더 있습니다만, 그다지 사용되지 않으므로 설명을 생략하도록 하겠습니다.)

INSTRREV 함수는 INSTR 함수와 사용법이 같은데.. 시작하는 위치가 반대입니다.
즉 INSTR 함수가 문자열의 처음부터 찾는 것에 반해, INSTRREV 함수는 문자열의 끝에서부터 역순으로(거꾸로) 찾는 것이지요.

intTest = INSTRREV (strTest, "그린")

이렇게 하면 intTest 값에는 25라는 숫자가 들어가게 됩니다.
끝에서부터 찾았을 때 가장 먼저 나온 문자열의 위치를 반환하는 것이지요.
이 함수는 '파일의 확장자' 를 알아낼 때에 특히 유용하고, 자주 쓰이는 함수입니다.
(그 내용에 관해서는 나중에 이야기할 기회가 있을 것 같네요. ^^)

INSTRREV 함수 역시 시작 위치를 설정할 수 있는데요..
INSTR 함수와는 다르게 세번째 인자로서 설정합니다. (혼동하지 마시기 바랍니다.)
시작 위치를 설정하면 그 위치부터 역순으로(거꾸로) 검색하게 되는 것이지요.

intTest = INSTRREV (strTest, "그린", 24)

이렇게 사용한 경우 intTest 값에는 19라는 값이 들어가게 됩니다.

5. LTRIM, RTRIM, TRIM

TRIM 이라는 함수는 단어 뜻 그대로 '잘라내는' 함수입니다.
아무거나 잘라내는 것은 아니고, 문자열의 앞뒤에 있는 '공백' 을 잘라내는 함수가 되겠습니다.
마찬가지로 LTRIM좌측의 공백을, RTRIM우측의 공백을 잘라내는 함수입니다.
이 함수들의 예를 들어보면 다음과 같습니다.

Dim strTest, strAll, strLeft, strRight

strTest = "    My Baby Grand    "
strAll = TRIM (strTest)
strLeft = LTRIM (strTest)
strRight = RTRIM (strTest)

strTest 라는 문자열의 앞,뒤로 3칸의 공백 문자가 들어가 있습니다.
그렇다면 TRIM 함수를 실행한 strAll 이라는 변수에는 어떤 값이 들어가게 될까요?
strAll 변수에는 양 옆의 공백이 사라진 "My Baby Grand" 이라는 문자열이 들어가게 됩니다.
마찬가지로 strLeft 에는 좌측의 공백이 사라진 "My Baby Grand???" 문자열이,
strRight 에는 우측의 공백이 사라진 "???MY Baby grand" 문자열이 들어가게 되는 것이지요.

사용자들이 어떤 페이지에서 값을 입력했을 때, 좌우에 공백을 포함하여 입력한 경우
상당히 유용하게 쓰이는 함수가 되겠습니다.

6. REPLACE

문자열 중에서 특정 내용을 다른 내용으로 바꾸려 할 때 REPLACE 함수를 사용합니다.
이 함수의 사용법은 다음과 같습니다.

Dim strBefore, strAfter

strBefore = "I like you.. Do you like me?"
strAfter = REPLACE (strBefore, "like", "love")

이것은 strBefore 이라는 변수에 담긴 "I like you.. Do you like me?" 라는 문자열 중에서
"like" 라는 문자를 찾아서 그것들만 "love" 라는 문자로 바꾸라는 의미가 되겠습니다.
이 함수를 실행하면 strAfter 이라는 변수에는 변경된 문자열인
"I love you.. Do you love me?" 값이 들어가게 되는 것입니다.
(당연한 이야기지만, 해당되는 문자열이 없을 때에는 문자열에 아무런 변화가 없게 됩니다.)

7. SPLIT

마지막으로 알아볼 함수는 SPLIT 함수입니다.
이 함수는 어떤 문자열에서 특정한 문자열 또는 기호를 기준으로 문자열을 분해한 다음,
분해된 문자열들을 배열에 저장하는 함수입니다.









여기서 잠깐!!

자.. 드디어 '배열' 이 나왔습니다.
(배열을 두려워하거나, 잘 안쓰시는 초보 분들이 의외로 많은 것 같더군요..)
지레 겁먹지 마시고, 차근차근하게 한번 이해해 보도록 하겠습니다.

배열은.. '관련있는 변수들의 모임' 이라고 생각하시면 이해가 빠를 것 같습니다.
예를 들어 주소록을 작성하려고 하는데, 사람들의 이름을 저장하기 위하여 이름마다 각각 다른 변수를 선언해서 저장하려 한다면 상당히 불편한 일이 될 것입니다.
예를 들면 다음과 같습니다.

Dim strNameOne, strNameTwo, strNameThree, strNameFour

strNameOne = "김덕영"
strNameTwo = "김태영"
strNameThree = "윤영지"
strNameFour = "장경수"

4명의 이름을 저장하기 위해서 하나하나 각각 변수를 지정하면 위처럼 사용해야 합니다.
이와 같은 경우에 배열을 사용하면 다음과 같이 표현할 수가 있겠습니다.

Dim arrName (3)

arrName (0) = "김덕영"
arrName (1) = "김태영"
arrName (2) = "윤영지"
arrName (3) = "장경수"

배열의 선언 방법은 간단합니다. 일반 변수의 오른쪽에 괄호만 붙여주면 되거든요.
우선 가장 윗 줄에서 arrName (3) 이라는 배열을 선언했습니다.
3이라는 숫자는 '이 배열이 4개의 항목을 가질 것이다' 라는 것을 알려주는 것입니다.

(자, 여기서 질문이 들어올 것 같군요. '4개의 항목인데 3이라니.. 오타지?' 라고 말이지요.
이것은 오타가 아닙니다. 우리는 숫자를 셀 때 1부터 세는 것을 당연스럽게 여기지만,
배열에서는 1이 아닌 0을 기준으로 합니다. 때문에 배열 요소의 개수는 언제나 괄호안의 숫자에 1을 더한 크기가 되는 것이지요.)

이렇게 배열이 선언되었다면, 위의 예에서 보듯이 숫자 (인덱스 번호)를 이용해
각각의 항목에 값을 저장할 수가 있습니다.

그렇다면 역으로.. 배열의 괄호 안에 들어가는 '인덱스 번호' 만 알고 있다면
아주 간단하게 그 '인덱스 번호' 에 해당하는 값을 알아낼 수가 있습니다.

배열에 대한 더 자세한 설명은 다음 기회에 보충하도록 하겠습니다.

SPLIT 의 사용 예를 들어보면 다음과 같습니다.

Dim arrName, strTest

strTest = "김덕영,김태영,윤영지,장경수"
arrName = SPLIT (strTest, ",")

strTest 라는 문자열에서는 쉼표(,) 를 기준으로 사람들의 이름을 구분하고 있습니다.
그래서 SPLIT 함수를 사용할 때 쉼표를 구분자로 사용하여 문자열을 분해했습니다.

이렇게 SPLIT 함수를 사용하고 난 후에 arrName 이라는 변수에는 배열이 저장되게 됩니다.
쉼표(,)를 기준으로 구분했을 때 가장 먼저 구분된 값은 "김덕영" 이 될테고요.
이 값은 배열의 가장 첫번째인 arrName (0) 에 저장되게 됩니다.
(배열에서 맨 처음은 1이 아닌 0이라는 사실을.. 반드시 기억하시기 바랍니다.)
마찬가지로 다음으로 구분된 값인 "김태영" 은 arrName (1) 에 저장되고,
이런 식으로 arrName (2) 에는 "윤영지", arrName (3) 에는 "장경수" 가 저장됩니다.

그렇게 저장된 값들은 '인덱스 번호' 를 이용하여 쉽게 접근할 수가 있습니다.
3번째로 구분된 값을 알고 싶다면 arrName (2) 라고 하면 되는 것이지요.
(위에서 말씀드렸지만 배열은 1이 아닌 0부터 시작하기 때문에 arrName (2) 가 됩니다.)

주의하실 점은, 범위를 초과하는 '인덱스 번호' 로 접근 하면 오류가 발생된다는 점입니다.
위의 예에서는 arrName (3) 까지만 값이 저장되었는데, 만약 arrName (4) 처럼
범위를 넘어선 '인덱스 번호' 로 접근하려 하면 오류가 발생된다는 뜻이지요.


자, 이것으로 '문자열 관련 함수' 에 관한 강좌를 마치도록 하겠습니다.
오늘의 강좌에서는 문자열을 다루는 대표적인 함수들에 대해서 알아보았습니다.
오늘 배운 함수들은 비교적 사용이 간편하고, 이해 하기가 비교적 쉬운 함수들인데요.
하지만 사용 빈도가 상당히 높아.. 앞으로 ASP 를 공부하면서 지겹도록 만나게 될 것 같습니다.

혹시나 지금 당장은 잘 이해가 가지 않는다고 하더라도,
이런 함수들이 있었다는 것 정도는 기억을 해 두시는 것이 좋겠습니다.
그래야 나중에 기능들을 필요로 할 때, 당황하지 않고 찾을 수가 있을테니까요. ^^

[프로그래밍] Regular Expression: ASP Strip Tags



This week, I have been mostly coding MAZIN. You will find out what that means when listening to Ram FM soon.


As part of the project, I had to create a page with a WYSIWYG editor (also known as Rich Text Editors) that would allow users to compose copy that may or may not include simple HTML tags such as bold, italic, lists, breaks and paragraphs.


As all sites we develop these days are XHTML based and standards compliant, I found that FCKEditor was the best choice - even though it is what Rich would call “Bloatware” - i.e, it’s rediculously large in terms of directories/language files/etc. That reminds me, I need to go through it and delete all the unwanted languages and plugin-in scripts before going live.


The problem with FCKEditor is that it will still allow users to post HTML that is not allowed i.e, you have told FCKEditor that you only want users to be able to make text bold, italic or whatever. This means that when we send the form, we need a strip_tags function, like PHP has.


Haven’t you already posted an ASP one!? I hear you ask. Well, I did. But the PHP version of strip_tags allows you to specify which tags you want to remain: www.php.net/strip_tags


After some researching, it seems that nobody has come up with an ASP version of this sweet function, so I wrote my own et voila:

'	=============================================================================================================

' @name stripHTML
' @desc strips all HTML from code except for tags seperated by commas in the param "allowedTags"
' @returns string
' =============================================================================================================
function stripHTML(strHTML, allowedTags)

dim objRegExp, strOutput
set objRegExp = new regexp

strOutput = strHTML
allowedTags = "," & lcase(replace(allowedTags, " ", "")) & ","

objRegExp.IgnoreCase = true
objRegExp.Global = true
objRegExp.MultiLine = true
objRegExp.Pattern = "< (.|
)+?>" ' match all tags, even XHTML ones
set matches = objRegExp.execute(strHTML)
objRegExp.Pattern = "< (/?)(w+)[^>]*>"
for each match in matches
tagName = objRegExp.Replace(match.value, "$2")
tagName = "," & lcase(tagName) & ","

if instr(allowedTags,tagName) = 0 then
strOutput = replace(strOutput, match.value, "")
end if
next

stripHTML = strOutput 'Return the value of strOutput
set objRegExp = nothing
end function



Usage is simple, just do:


html = stripHTML(html, "b,i,strong,em,p,br")


Where b, i, strong, em, p and br are the tags you are allowing.


That’s all for now





Useful Regular Expressions in ASP

ASP, Regular Expressions No Comments »

While working on an ASP ticket system today that required regular expressions, I came up with a couple of useful regular expression patterns that may save people a few hours of thinking time.


Matching and extracting a string


Problem: I have the following chunk of arbitrary text and I want to extract the order number prefixed “ORD_”:


The quick brown fox... ORD_1012345678 ...jumped over the lazy dog


Solution: ORD_[a-zA-Z0-9_-]*


What is going on? Well, quite simply the regular expression engine is being asked to match the first three letters “ORD” followed by an underscore “_”. It then requires a series (*) of letters, numbers, underscores or dashes (but nothing else). Therefore, once the regular expression engine has found the order number “ORD_1012345678″ and then it comes to a whitespace, new line, period or whatever - it stops parsing.


ASP VBScript Code:

Set regEx = New RegExp

With regEx
.Pattern = "ORD_[a-zA-Z0-9_-]*"
.IgnoreCase = true
.Global = false
End With
set matches = regEx.Execute(text)
if matches.count > 0 then
result = matches.item(0).value
end if


The string “ORD_1012345678″, extracted from the chunk of text, will be stored in the variable “result”


A very similar version of string extraction


Problem: I have the following chunk of arbitrary text and I want to extract the ID number in square brackets (prefixed “[#”):


The quick brown fox jumped over the lazy dog [#101234-56789]


Solution: [#([a-zA-Z0-9_-]*)


What is going on? In a similar way to the first one, this regular expression match pattern is asking for a square bracket followed by a hash “[#” - but because the opening square bracket is a reserved character (used to define sets), we have to escape it with a backwards slash before hand. We then surround the series of allowed characters with parenthesis ( ) which groups the match as a “sub match”.


ASP VBScript Code:

Set regEx = New RegExp

With regEx
.Pattern = "[#([a-zA-Z0-9_-]*)"
.IgnoreCase = true
.Global = false
End With
set matches = regEx.Execute(text)
if matches.count > 0 then
result = matches(0).subMatches(0)
end if


The ID number “101234-56789″ will be stored in “result”


The important difference to note in this code is the use of “subMatches(0)” which returns the first match found in the brackets.


Stripping HTML tags


This function can be used to strip HTML tags from a string. It is very similar to the PHP function strip_tags(); but this one is not as advanced (yet).


A more advanced version is now available here


Let’s just jump straight to the code, you don’t really need to know what is going on (you can probably guess anyway)…


ASP VBScript Code:

function stripTags(strHTML)

dim regEx
Set regEx = New RegExp
With regEx
.Pattern = "< (.|
)+?>"
.IgnoreCase = true
.Global = false
End With
stripTags = regEx.replace(strHTML, "")
end function


Trimming unwanted whitespace


If you want to trim unwanted whitespace from a string, e.g: turning “Text[space]spaced[space]normally[space][space][space]or[space][space]not?” into: “Text[space]spaced[space]normally[space]or[space]not?” use the following method:

function trimWhitespace(strIn, singleSpacing)

dim regEx
Set regEx = New RegExp
With regEx
.Pattern = "s+"
.IgnoreCase = true
.Global = false
End With
if singleSpacing then
space = " "
else
space = ""
end if
trimWhitespace = regEx.replace(strIn, space)
end function


When set to false, the second parameter “singleSpacing” will simply remove all whitespaces from a string, giving: “Textspacednormallyornot?”


I hope the above examples help someone!


You may find the following websites useful, I certainly did!


[프로그래밍] ASP 정규식 파일 파싱


Parsing Data Files
Data files come in a multitude of formats and descriptions. XML files, delimited text and even unstructured text are often the sources of the data our applications need. The example we'll look at below is a delimited text file that uses qualified strings - delimiters like quotes to indicate strings that must be kept together even if they contain the delimiter character used to split the records into individual fields.

A very plain and ordinary flat ASCII text data file might look like this:





LAST NAME, FIRST NAME, PHONE, QUOTE

Lowe, Richard, 312 555 1212, ASP is good
Huston, John, 847 555 1212, I make movies

In this file, the data is simply and atomically presented with a header (in caps) and two records with each field delimited by a comma character. Parsing is a simple matter of first splitting the file by rows (newline chars) and then dividing each record up into its fields. But what happens when you want to include a comma in the data itself:





LAST NAME, FIRST NAME, PHONE, QUOTE

Lowe, Richard, 312 555 1212, I like ASP, VB and SQL
Huston, John, 847 555 1212, I make movies

Trying to parse the first record creates a problem because the last record will be considered to be two fields by a parser that only considers commas. In order to circumvent this problem, fields that contain the delimiter character are qualified - distinguished usually by being enclosed in quotes. A text qualified version of the above data file would look like this:





LAST NAME, FIRST NAME, PHONE, QUOTE

Lowe, Richard, 312 555 1212, 'I like ASP, VB and SQL'
Huston, John, 847 555 1212, 'I make movies'

Now there is way to tell which commas should be used to split the record up and which should be left as part of a field, every comma inside the single quotes should be treated as part of the text. All that remains is to implement a regular expression parser that can tell when to split based on the comma and when not to. The challenge here is a bit different from most regular expressions. Typically, you will only be looking at a small portion of text and seeing if that matches your regular expression. But in this case, the only way to reliably tell what is inside the quotes is to consider the entire line at once. Here's an example of what I mean, take this partial line of text from a fictional data file:





1, Ford, Black, 21, ', dog, cat, duck, ',

Since there is data to the left of the 1, the above line is really quite ambiguous, we don't know how many single quotes have come before this segment of the data, and therefore we don't know which text is the qualified text (which we should not split up in our parsing). If there are an even number (or no) single quotes before this text, then ', dog, cat, duck, ' is a qualified string and should be kept together. If there are an odd number then 1, Ford, Black, 21, ' is the end portion of a qualified string and should be kept together.

To solve this our regular expression must examine the entire line of text and consider how many quotes appear in it to determine whether we are inside or outside of a set of quotes:





,(?=([^']*'[^']*')*(?![^']*'))

This regular expression first finds a comma, then looks to make sure there that the number of single quotes after the comma is either an even number or none at all. It works on the premise that an even number of quotes following a comma denotes that the comma is outside of a string. Here's how it breaks down:






























, Find a comma
(?= lookahead to match this pattern:
( start a new pattern
[^']*'[^']* [not a quote] 0 or many times then a quote
[^']*'[^']*) [not a quote] 0 or many times then a quote, combined with the one above it matches pairs of quotes
)* end the pattern and match the whole pattern (pairs of quotes) zero, or multiple times
(?! lookahead to exclude this pattern
[^']*' [not a quote] 0 or many times then a quote
) end the pattern

Here is a VBScript function that accepts a string and retuns an array which is split based on using commas as delimiters and the single quote as the text qualifier:





Function SplitAdv(strInput)

Dim objRE
Set objRE = new RegExp

' Set up our RegExp object
objRE.IgnoreCase = true
objRE.Global = true
objRE.Pattern = ",(?=([^']*'[^']*')*(?![^']*'))"

' .Replace replaces the comma that we will use with
' chr(8), the b character which is extremely unlikely
' to appear in any string it then splits the line into
' an array based on the b

SplitAdv = Split(objRE.Replace(strInput, "b"), "b")
End Function

In summary, parsing text data files with regular expressions is efficient and saves your development time, because you're spared from looping through your text to pick out complex patterns to break the file up with. In a highly transitional time where there is still plenty of legacy data floating around (data that is still very imporant to the businesses that use it), knowing how to create an efficient parsing routing is a valued skill.

In Part 4 we will conclude our examination of regular expression usage with an examination of using regular expressions to replace strings (providing much more power than the simple VBScript Replace function)!


[프로그래밍] ASP 정규식표현 RegExp Match


Extracting Specific Sections From An HTML Page
The main challenge in extracting data from an HTML page is finding a way to uniquely identify the section of data you are wanting to extract. Take for example this (fictional) HTML code snippet which shows the headline for a particular site:





<table border="0" width="11%" class="Somestory">

<tr>
<td width="100%">
<p align="center">In the news...</td>
</tr>
</table>
<table border="0" width="11%" class="Headline">
<tr>
<td width="100%">
<p align="center">It's War!</td>
</tr>
</table>
<table border="0" width="11%" class="Someotherstory">
<tr>
<td width="100%">
<p align="center">In the news...</td>
</tr>
</table>

Seeing this snippet makes it pretty obvious that the headline is presented in the middle table that has a class attribute set to Headline. (If you are getting HTML that is not directly controlled by you, you might find it handy to use an optional feature of IE that allows you to view partial source based on what you highlight: http://www.microsoft.com/Windows/ie/WebAccess/default.ASP). For this exercise, we'll assume that this is the only table with the class attribute set to Headline. (This example won't delve into the mechanics of grabbing information from another Web page - rather, this example will focus on picking out particular HTML from a page. To learn how to grab the HTML contents from another Web page through an ASP page, be sure to read: Grabbing Information From Other Web Servers and the FAQ: How can I treat some other web page as data on my own site?)

Now we need to create a regular expression that will find this and only this table to include in our pages. First, add the code supporting the regular expression:





<%

Dim re, strHTML
Set re = new RegExp ' creates the RegExp object

re.IgnoreCase = true
re.Global = false ' quits searching after first match
%>

Then we need to consider the area we want to capture: In this case we want the entire <table> structure with the ending tag and headline text (no matter what it is) intact. Start by finding the opening <table> tag:





re.Pattern = "<table.*(?=Headline)"

This will match the opening table tag and return everything after it (except new lines) up to the text Headline. Here is how you return the matched HTML:





' Puts all matched HTML in a collection called Matches:

Set Matches = re.Execute(strHTML)

' Show all the matching HTML:
For Each Item in Matches
Response.Write Item.Value
Next

' Show one specific piece:
Response.write Matches.Item(0).Value

Executed against our HTML snippet above, this expression returns one match that looks like this:





<table border="0" width="11%" class="

The (?=Headline) portion of the expression doesn't capture characters, so you won't see the class of the table in this partial match. Capturing the remainder of the table is quite simple for Version 5.5 (and greater) of VBScript (and JScript):





re.Pattern = "<table.*(?=Headline)(.|
)*?</table>"

To break it down: (.|
)
captures ANY charater, translated it means (any character except newline OR newline (which, obviously, translates to ANY character)). Followed by a * matches any charater 0 to many times and the ? makes the * non-greedy. Non-greedy means that the expression should match as little as possible before the next part of the expression is found. The </table> is the end of the Headline table.

The ? qualifier is important because it prevents the regular expression from returning the contents of other tables. For example in given the HTML snippet above, removing the ? from in front of the * would return this:





<table border="0" width="11%" class="Headline">

<tr>
<td width="100%">
<p align="center">It's War!</td>
</tr>
</table>
<table border="0" width="11%" class="Someotherstory">
<tr>
<td width="100%">
<p align="center">In the news...</td>
</tr>
</table>

It not only captured the ending <table> tag from the Headline table, but also from the Someotherstory table as well, thus the need for the non-greed qualifier (?). (For more information on the non-greedy qualifier, be sure to read: Picking Out Delimited Text with Regular Expressions!)

This example described a fairly ideal condition for returning portions of HTML, in the real world it is often more complicated, especially in cases where you don't have any influence over the source of the HTML you are pulling. The best approach is to examine small amounts of HTML surrounding the content you want to extract and build a regular expression slowly, testing often, to ensure you're getting only the matches you want. It's also important to handle the case where your regular expression doesn't match anything from the source HTML. Content can change quickly, and you want to ensure your page is not displaying an unprofessional looking error simply because someone else changed their content's format.

In Part 3 we'll look at another real-world use for regular expressions: parsing data files!


[프로그래밍] ASP 정규식 예제


이번글에서는 RegExp 객체가 가지고 있는 세 개의 메소드 (Method) 들 중에서 Replace() 메소드에 관해서 중점적으로 살펴보도록 하겠다. 쉽게 예상할 수 있겠지만 RegExp.Replace() 메소드는 작업 대상 문자열에서 지정한 정규 표현식 패턴을 만족하는 문자열(들)을 찾고 그 찾아낸 문자열(들)을 지정한 문자열로 치환한다.

다음의 코드는 ASP 상에서 Replace() 메소드를 사용하기 편리하도록 언제나처럼 필자가 미리 함수로 만들어 놓은 것으로서 역시 필요하신 분들께서는 각자의 상황에 알맞게 수정하여 사용하면 된다. 그리고, 이 코드는 이전글에서 Test() 메소드Execute() 메소드를 설명하기 위해서 만들었던 두 개의 함수, 즉 RegExpTest() 함수RegExpExec() 함수를 통해서 이미 익숙해진 패턴을 거의 그대로 따르고 있으므로 특별히 추가적인 설명은 필요없을 것이라고 믿고 바로 글을 진행하도록 하겠다.







 <% 


'******************************************************

'*

'* Public Function RegExpReplace(Patrn, TrgtStr, RplcStr)

'*

'* RegExp.Replace() 메소드를 일반화한 함수

'* '******************************************************

Public Function RegExpReplace(Patrn, TrgtStr, RplcStr)

Dim ObjRegExp

On Error Resume Next

Set ObjRegExp = New RegExp

ObjRegExp.Pattern = Patrn '** 정규 표현식 패턴

ObjRegExp.Global = True '** 문자열 전체를 검색함

ObjRegExp.IgnoreCase = True '** 대.소문자 구분 안함

RegExpReplace = ObjRegExp.Replace(TrgtStr, RplcStr)

Set ObjRegExp = Nothing

End Function %>

그렇다면 이제 실제로 이 함수를 사용하여 실무에서 빈번히 발생할 수 있을 듯한 사례를 처리해 보도록 하자. 다음은 Taeyo's ASP & .NETQ & A 메뉴 중, ASP 게시판 에서 발췌한 하나의 실제 사례이다. 이 질문의 원문을 올리셨던 분께는 필자가 E-Mail 로 인용에 대한 양해를 드렸으며 그 분께서는 별다른 조건없이 너무도 흔쾌히 인용을 허락을 해주셨다. 이 자리를 빌어서 다시 한 번 감사드린다.

이제 이 사례의 경우 발생한 문제점이 무었이었는지 다음의 글을 한 번 살펴보자.







데이타 베이스 내에서 가져올때 변환을 시켜서 가져올라고 하는데 좀처럼 쉽지 않네요.......
예를 들어 데이타 내에 테이블 사이즈인 width=500 이런것들이 불규칙하게 존재합니다......
그런데 그 데이타를 가져올때 테이블 크기땜에 자꾸 삐져나갑니다.....
그래서 Replace 함수를 써서 조금 변형 되게 가져 올라고 하는데.....특정한건 되지만
예를 들어 width 가 500 보다 큰것은 전부 500으로 바꾸어 줄라면 어떠케 해야 하나요??
데이타를 가져올때의 문제인가요??아님 방법이 없는걸까요??
도와주세요..........^^


즉 현재 데이타베이스의 특정 필드 (Filed) 에는 HTML 과 일반 문자열들이 혼합된 일련의 문장들이 저장되어져 있고, 이 문장들을 가져와서 미리 준비된 HTML Template 의 특정 위치에 출력하는 작업이 요구되는 상태이다. 그러나 한 가지 문제가 있는데 가져와야 될 문자열 내부에는 HTML Tag 들이 불규칙하게 섞여 있고 이 중 일부 HTML Tag 에 설정된 Width 어트리뷰트 (Attribute) 의 값 때문에 최종 출력물의 레이아웃 (Layout) 이 깨지는 현상이 발생하는 것이다.

이같은 상황은 게시판의 내용보기 페이지 등에서 HTML Tag 의 출력을 허용하는 경우라든가 또는 ASP.NET 의 Code Behind 와 같이 유지, 보수를 용이하게 하기 위한 목적으로 ASP 코드와 HTML 문서를 분리하기 위하여 자체적으로 HTML Template 을 정의하여 사용하는 경우 매우 흔하게 접할 수 있다. 이런 경우 대부분 문제가 되는 쪽은 기술적인 측면보다는 데이타베이스에서 가져온 HTML Tag 와 일반 문자열들의 혼합 문자열을 HTML Template 에 출력할 때 이 HTML Template 의 레이아웃이 파괴되어 버리는 현상이다.

가령 프로그래머는 폭 500 Pixel 의 테이블 안에 모든 내용을 출력하려는 생각으로 프로그램을 개발했다고 생각해보자. 그러나 실제로 사용자가 입력한 문자열 안에는 폭 600 Pixel 의 크기를 가진 Table Tag 가 포함되어져 있다면 결과적으로 폭 500 Pixel 의 테이블 내부에 폭 600 Pixel 인 테이블이 위치하게 되는 결과가 된다. 따라서 최종 출력물의 레이아웃이 일그러지는 것은 매우 당연한 일이고 위의 사례도 결국은 이와 같은 범주에 속한다고 말할 수 있을 것이다.


이와 동일한 사례를 설명하기 위해 다음과 같이 간단한 약식의 HTML 문자열을 가정해 보도록 하겠다. 지면 관계상 이처럼 작업 대상 문자열을 매우 짧고 간단하게 구성하였으나, 실제로는 보다 긴 문자열이나 HTML Tag 또는 일반 문자열들이 복잡하게 얽힌 문자열을 대상으로 하더라도 지금부터 설명하는 정규 표현식 처리의 결과는 동일하다.







<table border=0 cellpadding=0 cellspacing=0 width=550>
<table border=0 cellpadding=0 cellspacing=0 width=500>
<table border=0 cellpadding=0 cellspacing=0 width=450>
<table border=0 cellpadding=0 cellspacing=0 width=600>
<table border=0 cellpadding=0 cellspacing=0 width="650">
<table border=0 cellpadding=0 cellspacing=0 width='750'>

각 Table Tag 의 가장 끝 부분에 위치한 'Width' 어트리뷰트를 주의해서 보기 바란다. 여러가지 경우를 가정하기 위해 어트리뷰트의 값이 ''''"' 로 둘러쌓인 경우와 그렇지 않은 경우를 모두 포함시켰다. 일단은 가장 단순한 방법을 사용하여 이 문제를 해결해 보기로 한다. 즉 RegExp.Replace() 메소드만을 사용하고 'Width' 어트리뷰트의 값이 500 보다 큰 경우 무조건 값을 500 으로 치환하는 경우를 가정해보겠다.


결론부터 말해서 위의 RegExpReplace() 함수를 사용하여 이 문제를 해결하기 위한 코드는 다음과 같다. 조금 복잡하게 보이겠지만 알고 나면 간단하므로 너무 걱정하지 말기 바란다. 그리고 한 번 더 강조하지만 이 코드에 사용된 정규 표현식 패턴은 다만 필자가 이렇게 구성했다는 것일 뿐 이 문제에 대한 오직 하나뿐인 정답은 절대 아니며 이보다 더 효율적인 정규 표현식 패턴도 얼마든지 만들어 낼 수 있다는 점을 기억하기 바란다.

    RegExpReplace("(<table.*width=(?:|'|""))([56789]d{2}|d{4})((?:|'|"").*>)", Sample_String, "$1500$3")


이제 이러한 결과가 나오기까지의 과정을 한 번 차분히 살펴보도록 하자. 당면한 문제는 결국 세 자리 혹은 네 자리로 된 숫자들을 비교하고 500 보다 큰 경우 500 으로 치환해 주어야 하는데 거슬리는 부분은 숫자라고해서 아무 숫자나 막 바꿀수가 없다는 것이다. 즉 HTML Tag 가 아닌 일반 문자열 중에서도 숫자값이 있을 수 있고 HTML Tag 중에서도 특정 Tag 의 숫자만 바꾸어야 하는 경우도 있다. 이에 더하여 하나의 HTML Tag 내에서도 여러 개의 어트리뷰트들이 비슷한 숫자값을 가지는 경우가 허다하다.

따라서 우리가 원하는 HTML Tag 에서 원하는 어트리뷰트의 값만 비교하여 치환을 해주어야 하는데 바로 이것이 난제인 것이다. 먼저 우리의 관심의 대상인 Width=xxx 부분을 살펴보도록 하자. 필자는 이 부분을 다음과 같이 구성하였다.

    width=(?:|'|")([56789]d{2}|d{4})(?:|'|")


당연히 이 정규 표현식 패턴의 가장 처음 부분은 width= 로 시작된다. 그리고 그 다음 부분에는 실제 숫자값이 위치하게 되는데 여기에서 한 가지 고려해야 할 사항이 있다. 실제로 현업에서 HTML 문서를 작성할 때는 width=xxx, width='xxx', 그리고 width="xxx" 와 같은 세 가지 유형의 어트리뷰트 값 표현 방식들이 모두 비슷한 빈도로 사용된다는 점이다. 사견으로 이러한 특성은 HTML 의 가장 나쁜 일면 중 하나라고 생각하는데 이러한 특성은 결국 HTML 문서의 유효성 (Validation) 을 엉망으로 만드는 원인이 되기 때문이다.

따라서 정규 표현식 패턴을 작성할 때에도 이런 점을 고려해 주어야만 하고 필자는 이를 (?:|'|") 라는 정규 표현식 패턴으로 구성했다. 즉 아무것도 없거나 ' (작은따옴표) 이거나 " (큰따옴표) 인 경우를 찾는 것이다. 이 때 한 가지 주의해야 할 점은 VBScript 에서 " 는 문자열을 의미하는 리터럴이므로 실제로 RegExpReplace() 함수에서 사용할 때는 "" 로 바꿔주어야 한다는 것이다.

그리고 이 부분에서 단순히 소괄호를 사용하지 않고 ?: 메타 문자를 사용하여 (?:...) 형식으로 표현한 것은 지난 글에서도 한 번 설명했지만 역참조를 사용하지 않기 위한 것이다. 일단 이 부분에 대해서는 잠시 설명없이 넘어가도록 한다.

이번엔 실제로 치환이 이루어져야 할 숫자 부분을 살펴보자. 현재 조건을 고려해 볼 때 3 자리 이하의 숫자는 치환할 필요가 없으며 5 자리 이상의 숫자도 일반적으로 유통되는 그래픽 카드에서 지원되는 해상도를 고려해 볼 때 그다지 큰 의미가 없다. 따라서 결국 3 자리 숫자 또는 4 자리 숫자만 고려하면 된다는 결론인데 이와 같은 조건은 ([56789]d{2}|d{4}) 이라는 정규 표현식 패턴으로 표현이 가능하다. 즉 5 에서 9 사이의 숫자로 시작되는 모든 3 자리 숫자, 또는 모든 4 자리 숫자를 찾는 것이다. 결국 이와 같이 구성된 정규 표현식 패턴의 조각들을 모두 조합하면 width=(?:|'|")([56789]d{2}|d{4})(?:|'|") 이라는 정규 표현식을 얻을 수 있다.

이제 그 다음 나머지 부분들에 관해 생각해 보자. 지금 우리에게 필요한 것은 무조건 문자열 내부에 존재하는 모든 width="xxx" 스타일의 문자열을 치환하는 것이 아니다. 단지 Table Tag 내부에 존재하는 width="xxx" 스타일의 문자열만을 치환해야 하는 것이다. 따라서 정규 표현식 <table.*.*> 를 위에서 만든 정규 표현식의 앞뒤에 추가하면 다음과 같은 결과가 나오게 된다.

    <table.*width=(?:|'|")([56789]d{2}|d{4})(?:|'|").*>


지금까지의 과정을 모두 잘 이해했다면 이제 정규 표현식 전체을 통틀어서 가장 흥미로운 기능이라고 말할 수 있는 역참조 기능에 대해서 알아봐야 될 순서다. 위와 같이 구성된 정규 표현식 패턴 그 자제만으로는 당연히 치환이 불가능하다. 치환할 대상 문자열을 찾기위해서 이처럼 정규 표현식 패턴을 구성했지만 아직까지 찾아낸 대상 문자열을 어떻게 치환할 것인가는 결정하지 않았기 때문이다. 정규 표현식에서는 패턴과 일치하는 문자열들을 찾아 놓고서 찾은 문자열의 일부분들을 조합하여 치환에 재사용할 수가 있는데 이러한 기능을 '역참조' 라고 한다. 만약 정규 표현식에서 이 역참조가 불가능했다면 문자열 처리 작업에 정규 표현식을 사용해야 할 이유가 크게 줄어들었을 것이다.

일반적으로 대상 문자열에서 치환을 하고자 하는 부분은 패턴 전체가 아니라 패턴의 일부분인 경우가 많고 지금의 사례와 같은 경우도 마찮가지다. 우리가 치환하기를 원하는 부분은 <Table ... > Tag 전체가 아니라, 단지 그 중 일부인 width="xxx" 일 뿐이다. 이와 같은 경우 역참조 기능이 매우 유용하게 사용되는데 다음을 보도록 하자. 위에서 작성한 정규 표현식을 크게 세 부분으로 나누었다.

    <table.*width=(?:|'|")  +  ([56789]d{2}|d{4})  +  (?:|'|").*>


위와 같은 세 부분 중에서 우리가 치환하기를 원하는 부분은 단지 가운데 부분뿐이다. 오히려 처음 부분과 끝 부분은 바뀌면 절대 안된다. 이 정규 표현식을 다음과 같이 각각 소괄호로 묶어보자.

    (<table.*width=(?:|'|"))  +  (([56789]d{2}|d{4}))  +  ((?:|'|").*>)


그리고, 다시 합친다.

    (<table.*width=(?:|'|"))(([56789]d{2}|d{4}))((?:|'|").*>)


이제 정규 표현식이 완성되었다. 이와 같이 소괄호를 잘 사용하면 재미있는 작업이 가능해진다. 이 정규 표현식 패턴으로 RegExp.Replace() 메소드를 실행시키면 패턴에 매치되는 각각의 문자열을 찾을 때마다 미리 약속된 변수명 $n (여기에서 n 은 1, 2, 3 ...) 으로 패턴의 소괄호안에 있는 문자열들을 순서대로 저장해둔다.

즉, 위의 사례의 경우 가장 첫 번째로 패턴과 일치하는 문자열은 <table border=0 cellpadding=0 cellspacing=0 width=550> 이 될 것이다. 이 때 패턴에 사용된 소괄호를 따져보면 다음과 결론을 얻을 수 있다.

    $1 이라는 변수에 문자열 "<table border=0 cellpadding=0 cellspacing=0 width=" 이 저장된다.

    $2 이라는 변수에 문자열 "550" 이 저장된다.

    $3 이라는 변수에 문자열 ">" 이 저장된다.


그리고, 더욱 고무적인 사실은 이 $n 변수를 바로 아래의 Code 에서와 같이 치환할 문자열에서 사용할 수 있다는 점이다. 아래에서 파랗게 강조된 부분이 바로 치환할 문자열을 나타내는 부분인데 결국 이 문자열은 역참조 변수 $1 과 바꾸려는 값 500 그리고 또 하나의 역참조 변수 $3 이 결합된 문자열인 것이다.

    RegExpReplace("(<table.*width=(?:|'|""))([56789]d{2}|d{4})((?:|'|"").*>)", Sample_String, "$1500$3")


따라서 방금 예로 들었던 가장 첫 번째로 패턴과 일치하는 문자열 <table border=0 cellpadding=0 cellspacing=0 width=550> 의 경우 아래와 같은 작업이 벌어지게 되고 <table border=0 cellpadding=0 cellspacing=0 width=550> 문자열은 아래의 작업 결과로 만들어진 <table border=0 cellpadding=0 cellspacing=0 width=500> 으로 치환된다.

    $1 + 500 + $3  =  "<table border=0 cellpadding=0 cellspacing=0 width=" + "500" + ">"
                            =  "<table border=0 cellpadding=0 cellspacing=0 width=500>"



주의해야 할 점은 위에서도 한 번 얘기했던 것처럼 (?:...) 과 같이 ?: 등의 메타 문자가 포함된 소괄호의 경우에는 따로 그 부분을 $n 변수에 저장하지 않는다는 것이다. 일련의 ?: 메타 문자 시리즈들은 바로 그런 목적을 위해 만들어진 것으로 그 외에도 각각 특수한 기능들을 가지고 있다. 이에 관한 추가적인 사항은 각자 알아보기 바란다.

다음은 지금까지 설명한 내용을 처리하는 실제 코드이다. 출력을 위해서 Replace() 함수를 몇 번 호출하는 부분이나 검색 대상 문자열을 만드는 부분을 빼고 나면 지금까지의 긴 설명이 무색할 정도로 간단하다.







 <% 


Dim Sample_String '** 치환 대상 문장을 담을 변수

Dim Result_String '** 치환 결과를 담을 변수

Dim RegExp_String '** 정규 표현식 패턴을 담을 변수

'** 검색 대상 문장

Sample_String = "<table border=0 cellpadding=0 cellspacing=0 width=550>" & vbCRLF & _

"<table border=0 cellpadding=0 cellspacing=0 width=500>" & vbCRLF & _

"<table border=0 cellpadding=0 cellspacing=0 width=450>" & vbCRLF & _

"<table border=0 cellpadding=0 cellspacing=0 width=600>" & vbCRLF & _

"<table border=0 cellpadding=0 cellspacing=0 width=""650"">" & vbCRLF & _

"<table border=0 cellpadding=0 cellspacing=0 width='700'>"

'** 정규 표현식 문장

RegExp_String = "(<table.*width=(?:|'|""))([56789]d{2}|d{4})((?:|'|"").*>)"

'** RegExpReplace() 함수 실행
String, 


"$1500$3") Result_String = Server.HTMLEncode(Result_String)

Response.Write Replace(Result_String, vbCRLF, "<br>") %>

정규 표현식에 관한 첫 번째 글에서 필자가 날짜 문자열을 처리하는 방법에 관해서 얘기했던 적이 있다. 이번에 그와 같은 날짜 문자열들에 대한 간단한 예를 살펴본다. '2000년 10월 13일''10/13/2000' 형식으로 치환하려면 다음과 같은 코드를 사용하면 된다.

    RegExpReplace("(d{4})년 (d+)월 (d+)일", "2000년 10월 13일", "$2/$3/$1")


또한, 그 반대의 경우는 다음과 같다.

    RegExpReplace("(d+)/(d+)/(d{4})", "10/13/2000", "$3년 $1월 $2일")


이 정도 수준만 되도 불편했던 프로그래밍이 한결 수월해진다. 그러나 당연한 얘기겠지만 RegExp.Replace() 메소드도 만능은 아니다. 예를 들어 위의 사례에서와 같은 경우 Width 어트리뷰트의 값을 항상 500 으로 치환해야 하는 것이 아니라, 기존의 값에 20 을 더한 값으로 치환해야 한다면 위의 정규 표현식은 사용할 수 없다.

즉, 다음과 같은 코드는 원하는 대로의 결과가 나오지 않는다는 뜻이다.

    RegExpReplace("(<table.*width=(?:|'|""))([56789]d{2}|d{4})((?:|'|"").*>)", Sample_String, "$1($2+20)$3")


이는 정규 표현식이 문자열들의 모든 요소를 말 그대로 일괄적으로 문자열로 취급하기 때문인데 이런 경우에는 지난번 글에서 설명했던 RegExp.Execute() MethodMatches Collection, SubMatches Collection 등의 기능과 함께 VBScript 의 일반적인 함수들을 사용하여 추가적인 작업을 구성해 주어야 한다. 사실 역참조 변수 $n 은 SubMatches Collection 의 Item 들과 정확하게 일 대 일로 대응되는 개념이다.

그리고 필자의 사견으로는 VBScript 의 정규 표현식 처리는 Perl 과 같은 여타 다른 프로그래밍 언어들의 그 것에 비교하여 상당히 부족하다는 느낌이다. 물론 구버전의 VBScript 에서 정규 표현식이 지원되지조차 않았던 것을 생각한다면 지금의 상태도 매우 큰 발전이겠지만 아쉬움이 남는 것은 어쩔수 없는 것 같다.

그러나 그렇다고 해서 VBScript 에서의 정규 표현식에 투자하는 시간이 낭비라고는 생각하지 않는다. 나름대로 VBScript 의 정규 표현식은 Visual Basic.NET 의 정규 표현식 기능으로 접근해 나가는 과도기적인 역활을 훌륭히 수행할 수 있다고 생각하며 그 자체만으로도 매우 강력한 기능을 가지고 있다.

또한 정규 표현식 자체가 특정 프로그래밍 언어에 종속되는 것이 아니고 해당 언어에서 정규 표현식을 얼마나 충실하게 구현했는가에 따라 그 특성이 바뀌는 것이므로, 비교적 접근하기 쉬운 VBScript 의 정규 표현식은 아마도 다른 프로그래밍 언어들의 정규 표현식 구현에 접근하기 위한 좋은 시작점이 될 수 있지 않을까 한다.


역시 이번글도 그 분량이 필자의 예상을 휠씬 초과했다. 지난번 글에서도 얘기했지만 원래 이번글에서는 위에서 설명한 RegExp.Replace() 메소드와 함께 JavaScript 상에서의 정규 표현식을 간략하게나마 소개하고 넘어가려고 했었다. 그러나 글의 분량이 약간 어정쩡해져 버려서 애초에 의도했던 것과는 달리 이번 글은 이정도에서 마무리를 해야 할 것 같다. JavaScript 상에서의 정규 표현식에 관한 내용도 나름대로 그 분량이 매우 많기 때문에 괜한 무리를 하는 것은 바람직한 일이 아닐것 같다.

그리고 아쉽지만 다음글에서도 역시 JavaScript 상에서의 정규 표현식에 관한 내용은 다루지 않는다. 지금 진행되고 있는 일련의 글들은 모두 VBScript 5.6 의 특성에 관한 것으로 일종의 연재물적인 성격을 가지고 있다. 따라서 지금 갑자기 JavaScript 에 관한 이야기를 새로 시작하는 것은 전체적인 글의 흐름에 있어 무리를 가져올 것 같다는 생각이다.

그런 이유로 JavaScript 상에서의 정규 표현식에 관한 얘기는 VBScript 5.6 에 관한 글들이 모두 마무리된 후에야 비로소 다시 시작할 수 있을 것 같다. 다음글에서는 VBScript 5.6 의 클래스 (Class) 에 관해서 알아보고 지면이 허락된다면 이 클래스를 이용하는 Remote Scripting 에 관해서도 알아보도록 하겠다.



[프로그래밍] Content 중 URL을 자동으로 인식하여 링크를 시켜주는 함수


해당 함수는 Content 중 URL을 자동으로 인식하여 링크를 시켜주는 함수 입니다.

<HTML>

<HEAD>
<TITLE>ASP 정규식</TITLE>
</HEAD>
<BODY>
<h1>ASP 정규식</h1><p>
<font size=2 face=굴림>
<%
Function UrlLink(strng)
Dim regEx
Set regEx = New RegExp
regEx.Pattern = "([^=""|='](http|https|ftp|telnet|news)://[a-z0-9-]+.[][a-zA-Z0-9:&#@=_~%;?/.+-]+)"
regEx.IgnoreCase = True
regEx.Global = True
UrlLink = regEx.Replace(strng,"<a href='$1' target='_blank'>$1</a>")
End Function

content = "홈페이지 : http://www.ihelpers.co.kr"

response.write "<b>Source : </b>" & content & "<br>"
response.write "<b>함수적용 : </b>" & UrlLink(content)
%>
</font>
</BODY>
</HTML>

[프로그래밍] webthumb -- web page snapshot-taker for Linux



WEBTHUMB(8)






WEBTHUMB(8)
Linux System Manager's Manual
WEBTHUMB(8)

NAME

webthumb -- web page snapshot-taker for Linux

SYNOPSIS

webthumb URL

PRACTICAL EXAMPLE

Take a snapshot of our home page and reduce it to a thumbnail no larger than 100x100, preserving the original aspect ratio (enter this command as one line, of course):

webthumb http://www.boutell.com/ | pnmscale -xysize 100 100 | pnmtojpeg > thumb.jpg

VERSION

Version 1.01, 12/31/2003. Version 1.01 adds locking, which forces webthumb tasks to run sequentially so that each task receives the correct screenshot.

REQUIREMENTS

You must have the following tools, which are often already installed and/or available as packages for your Linux distribution:


  • The Xvfb virtual framebuffer X server. Sometimes not installed by default, but easily available as a package for Red Hat, Debian, et cetera.
  • The Mozilla web browser.
  • The netpbm image manipulation utilities. Almost always installed; it's easy to build them yourself or install them as a package.
  • The Linux operating system. webthumb uses the /proc file system to determine whether processes are still running properly.

WHERE TO GET

Download from our web server.

DESCRIPTION

Creates a PPM-format image of the first screenful of a web page and writes this image to standard output. This is done using the Xvfb virtual framebuffer X server, which provides an environment for the mozilla web browser. To minimize CPU impact, the Xvfb and mozilla processes are kept resident in memory and reused by future invocations of webthumb. See the top of the Perl source for useful settings.

BUGS

The "chrome" of the browser is displayed. This could be fixed with a set of custom XUL files and the -chrome command line option. If you have run Mozilla or Netscape 4 interactively as the current Unix user before, Mozilla may display dialog boxes telling you about profile upgrades and so forth, which prevent the display of the desired page. This can be addressed by deleting the .mozilla and .netscape folders from the home directory of the current Unix user, if they do not contain files that are important to you. It would be nice if webthumb could set up your Mozilla preferences at first use in an appropriate way.

In an ideal world, mozilla would have a command line option like this:

mozilla -htmltops URL (THIS DOESN'T REALLY EXIST)

In order to produce a high-quality postscript version of a web page without the need for any X server at all, and this could then be piped through ghostscript to produce all manner of great things. But there is no such feature, so webthumb is a handy workaround.