Ver3.0 ๐ฏ C++ ์ ๊ทํํ์๊ณผ std::regex๋ฅผ ํ์ฉํ ํ ์คํธ ์ฒ๋ฆฌ

๐ฏ C++ ์ ๊ทํํ์๊ณผ std::regex๋ฅผ ํ์ฉํ ํ ์คํธ ์ฒ๋ฆฌ
์น๊ตฌ์ฒ๋ผ ์ฝ๊ฒ ๋ฐฐ์ฐ๋ ํ ์คํธ ๋ง๋ฒ์ฌ ๋๊ธฐ ํ๋ก์ ํธ! โจ
๐ ์ ๊ทํํ์, ๋ ๋๊ตฌ๋?
์ผ, ํน์ ํ ์คํธ ํ์ผ์์ ์ด๋ฉ์ผ ์ฃผ์๋ง ์์ ๋ฝ์๋ด๊ฑฐ๋, ์ ํ๋ฒํธ ํ์์ด ๋ง๋์ง ๊ฒ์ฌํ๊ฑฐ๋, ํน์ ํจํด์ ๋ฌธ์์ด์ ํ ๋ฒ์ ๋ฐ๊ฟ์ผ ํ ๋ ๋ง๋งํ๋ ์ ์์ง? ๐ ๊ทธ๋ด ๋ ํ์ํ ๊ฒ ๋ฐ๋ก ์ ๊ทํํ์(Regular Expression)์ด์ผ!
์ ๊ทํํ์์ ์ฝ๊ฒ ๋งํด์ ๋ฌธ์์ด ํจํด์ ํํํ๋ ํน๋ณํ ์ธ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ. ๋ง์น "010์ผ๋ก ์์ํ๊ณ ์ซ์ 8๊ฐ๊ฐ ๋ ์๋ ๊ฑฐ ์ฐพ์์ค!"๋ผ๊ณ ์ปดํจํฐ์๊ฒ ๋ช ๋ นํ๋ ๊ฑฐ์ง. ์ด๊ฑธ C++์์ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ ๋ฐ๋ก std::regex ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ! ๐
C++11๋ถํฐ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํจ๋์ด์, ๋ณ๋์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ด๋ ๊ฐ๋ ฅํ ํ ์คํธ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๊ฒ ๋์ด. ์ด์ ๋ถํฐ ์น๊ตฌ์ฒ๋ผ ํธํ๊ฒ ํ๋์ฉ ์์๋ณด์!
๐ std::regex ๊ธฐ๋ณธ ๊ตฌ์กฐ ํํค์น๊ธฐ
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก C++์ std::regex๋ฅผ ์ฌ์ฉํด๋ณด์! ๋จผ์ ํ์ํ ํค๋ ํ์ผ์ ํฌํจ์์ผ์ผ ํด:
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string text = "๋ด ์ด๋ฉ์ผ์ hello@example.com ์ด์ผ!";
std::regex pattern("[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z]+");
if (std::regex_search(text, pattern)) {
std::cout << "์ด๋ฉ์ผ์ ์ฐพ์์ด! ๐" << std::endl;
}
return 0;
}
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ธ ๊ฐ์ง ํต์ฌ ์์๊ฐ ์์ด:
1๏ธโฃ std::string - ๊ฒ์ํ ํ ์คํธ๋ฅผ ๋ด๋ ๋ฌธ์์ด
2๏ธโฃ std::regex - ์ฐพ๊ณ ์ถ์ ํจํด์ ์ ์ํ๋ ์ ๊ทํํ์ ๊ฐ์ฒด
3๏ธโฃ std::regex_search - ์ค์ ๋ก ํจํด์ ์ฐพ์์ฃผ๋ ํจ์
๐ ์ฃผ์ ํจ์๋ค ์ด์ ๋ฆฌ
std::regex ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ฌ๋ฌ ๊ฐ์ง ์ ์ฉํ ํจ์๋ค์ ์ ๊ณตํด. ๊ฐ๊ฐ์ ํน์ง์ ์์๋ณด์!
| ํจ์๋ช | ๊ธฐ๋ฅ | ์ฌ์ฉ ์๋๋ฆฌ์ค |
|---|---|---|
| regex_match | ์ ์ฒด ๋ฌธ์์ด์ด ํจํด๊ณผ ์ผ์นํ๋์ง ํ์ธ | ์ ๋ ฅ๊ฐ ์ ์ฒด ๊ฒ์ฆ (์: ๋น๋ฐ๋ฒํธ ํ์) |
| regex_search | ๋ฌธ์์ด ๋ด์์ ํจํด์ ์ฐพ์ | ํ ์คํธ์์ ํน์ ํจํด ์ฐพ๊ธฐ |
| regex_replace | ํจํด๊ณผ ์ผ์นํ๋ ๋ถ๋ถ์ ์นํ | ๋ฌธ์์ด ์ผ๊ด ๋ณ๊ฒฝ |
| regex_iterator | ๋ชจ๋ ๋งค์นญ ๊ฒฐ๊ณผ๋ฅผ ์ํ | ์ฌ๋ฌ ๊ฐ์ ๋งค์นญ ๊ฒฐ๊ณผ ์ฒ๋ฆฌ |
๐จ ์ ๊ทํํ์ ํจํด ๋ฌธ๋ฒ ๋ง์คํฐํ๊ธฐ
์ ๊ทํํ์์ ์ง์ง ํ์ ํจํด ๋ฌธ๋ฒ์ ์์ด! ์ฒ์์ ์ข ๋ณต์กํด ๋ณด์ด์ง๋ง, ํ๋์ฉ ์ตํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋ผ. ๐
๐ค ๊ธฐ๋ณธ ๋ฌธ์ ํด๋์ค
. (์ ) - ์ค๋ฐ๊ฟ์ ์ ์ธํ ๋ชจ๋ ๋ฌธ์ ํ๋์ ๋งค์นญ
\d - ์ซ์ ํ๋ [0-9]์ ๋์ผ
\D - ์ซ์๊ฐ ์๋ ๋ฌธ์
\w - ๋จ์ด ๋ฌธ์ [a-zA-Z0-9_]
\W - ๋จ์ด ๋ฌธ์๊ฐ ์๋ ๊ฒ
\s - ๊ณต๋ฐฑ ๋ฌธ์ (์คํ์ด์ค, ํญ, ์ค๋ฐ๊ฟ)
\S - ๊ณต๋ฐฑ์ด ์๋ ๋ฌธ์
// ์ซ์ 3๊ฐ ์ฐพ๊ธฐ
std::regex pattern1("\\d{3}"); // 123, 456 ๋ฑ
// ๋จ์ด ์ฐพ๊ธฐ
std::regex pattern2("\\w+"); // hello, world123 ๋ฑ
// ๊ณต๋ฐฑ์ผ๋ก ๊ตฌ๋ถ๋ ๋จ์ด๋ค
std::regex pattern3("\\w+\\s+\\w+"); // "hello world" ๋ฑ
๐ก ๊ฟํ! C++์์๋ ๋ฐฑ์ฌ๋์๋ฅผ ์ด์ค์ผ์ดํํด์ผ ํด์ \\d์ฒ๋ผ ๋ ๋ฒ ์จ์ผ ํด. ์ด๊ฒ ์ข ๊ท์ฐฎ์ผ๋ฉด raw string literal์ ์ฌ์ฉํ ์ ์์ด: R"(\d{3})" ์ด๋ ๊ฒ!
๐ข ์๋์ (Quantifiers)
์๋์๋ ํจํด์ด ๋ช ๋ฒ ๋ฐ๋ณต๋๋์ง๋ฅผ ์ง์ ํด์ค. ์ด๊ฒ ์ ๋ง ์ ์ฉํด!
* - 0๋ฒ ์ด์ ๋ฐ๋ณต (์์ด๋ ๋๊ณ , ์ฌ๋ฌ ๋ฒ ์์ด๋ ๋จ)
+ - 1๋ฒ ์ด์ ๋ฐ๋ณต (์ต์ 1๋ฒ์ ์์ด์ผ ํจ)
? - 0๋ฒ ๋๋ 1๋ฒ (์๊ฑฐ๋ ์๊ฑฐ๋)
{n} - ์ ํํ n๋ฒ
{n,} - n๋ฒ ์ด์
{n,m} - n๋ฒ ์ด์ m๋ฒ ์ดํ
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string text = "์ ํ๋ฒํธ: 010-1234-5678, 02-123-4567";
// ํด๋ํฐ ๋ฒํธ ํจํด (010-xxxx-xxxx)
std::regex mobile(R"(010-\d{4}-\d{4})");
// ์ผ๋ฐ ์ ํ๋ฒํธ ํจํด (0x-xxx-xxxx ๋๋ 0xx-xxxx-xxxx)
std::regex phone(R"(0\d{1,2}-\d{3,4}-\d{4})");
std::smatch match;
if (std::regex_search(text, match, mobile)) {
std::cout << "ํด๋ํฐ: " << match.str() << std::endl;
}
return 0;
}
๐ฏ ์ต์ปค์ ๊ฒฝ๊ณ
๋ฌธ์์ด์ ์์์ด๋ ๋, ๋จ์ด์ ๊ฒฝ๊ณ๋ฅผ ์ง์ ํ ์ ์์ด:
^ - ๋ฌธ์์ด์ ์์
$ - ๋ฌธ์์ด์ ๋
\b - ๋จ์ด ๊ฒฝ๊ณ (๋จ์ด์ ์์์ด๋ ๋)
\B - ๋จ์ด ๊ฒฝ๊ณ๊ฐ ์๋ ๊ณณ
// ๋ฌธ์์ด์ด ์ซ์๋ก๋ง ์ด๋ฃจ์ด์ ธ ์๋์ง ํ์ธ
std::regex only_digits(R"(^\d+$)");
// "cat"์ด๋ผ๋ ๋จ์ด๋ง ์ฐพ๊ธฐ ("catch"์ cat์ ์ ์ธ)
std::regex word_cat(R"(\bcat\b)");
std::string test1 = "12345";
std::string test2 = "abc123";
std::string test3 = "I have a cat";
std::string test4 = "I catch fish";
std::cout << std::regex_match(test1, only_digits) << std::endl; // 1 (true)
std::cout << std::regex_match(test2, only_digits) << std::endl; // 0 (false)
std::cout << std::regex_search(test3, word_cat) << std::endl; // 1 (true)
std::cout << std::regex_search(test4, word_cat) << std::endl; // 0 (false)
๐ ๏ธ ์ค์ ์์ ๋ก ๋ฐฐ์ฐ๋ std::regex
์ด๋ก ์ ์ด์ ์ถฉ๋ถํด! ์ค์ ๋ก ์์ฃผ ์ฌ์ฉํ๋ ํจํด๋ค์ ์ฝ๋๋ก ๊ตฌํํด๋ณด์. ๐
๐ง ์ด๋ฉ์ผ ์ฃผ์ ๊ฒ์ฆํ๊ธฐ
์ด๋ฉ์ผ ์ฃผ์๋ ์น ๊ฐ๋ฐ์์ ๊ฐ์ฅ ๋ง์ด ๊ฒ์ฆํ๋ ํจํด ์ค ํ๋์ผ. ์๋ฒฝํ ์ด๋ฉ์ผ ๊ฒ์ฆ์ ๋ณต์กํ์ง๋ง, ์ค์ฉ์ ์ธ ์์ค์ ๊ฒ์ฆ ์ฝ๋๋ฅผ ๋ง๋ค์ด๋ณด์:
#include <iostream>
#include <regex>
#include <string>
#include <vector>
bool validateEmail(const std::string& email) {
// ์ด๋ฉ์ผ ํจํด: ์๋ฌธ์/์ซ์/ํน์๋ฌธ์ + @ + ๋๋ฉ์ธ + . + ์ต์์๋๋ฉ์ธ
std::regex pattern(
R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)"
);
return std::regex_match(email, pattern);
}
int main() {
std::vector<std::string> emails = {
"user@example.com", // โ
์ ํจ
"test.user@domain.co.kr", // โ
์ ํจ
"invalid@", // โ ๋ฌดํจ
"@invalid.com", // โ ๋ฌดํจ
"no-at-sign.com" // โ ๋ฌดํจ
};
for (const auto& email : emails) {
std::cout << email << " : "
<< (validateEmail(email) ? "โ
์ ํจ" : "โ ๋ฌดํจ")
<< std::endl;
}
return 0;
}
๐ ์ฐธ๊ณ : ์ ํจํด์ ์ผ๋ฐ์ ์ธ ์ด๋ฉ์ผ ํ์์ ๊ฒ์ฆํด. RFC 5322 ํ์ค์ ์๋ฒฝํ๊ฒ ๋ฐ๋ฅด๋ ค๋ฉด ํจ์ฌ ๋ณต์กํ ํจํด์ด ํ์ํ์ง๋ง, ์ค๋ฌด์์๋ ์ ์ ๋๋ฉด ์ถฉ๋ถํด!
๐ฑ ์ ํ๋ฒํธ ์ถ์ถ ๋ฐ ํฌ๋งทํ
ํ ์คํธ์์ ์ ํ๋ฒํธ๋ฅผ ์ฐพ์์ ํต์ผ๋ ํ์์ผ๋ก ๋ฐ๊ฟ๋ณด์:
#include <iostream>
#include <regex>
#include <string>
std::string formatPhoneNumber(const std::string& text) {
// ๋ค์ํ ์ ํ๋ฒํธ ํ์์ ์ฐพ๋ ํจํด
// 010-1234-5678, 01012345678, 010.1234.5678 ๋ฑ
std::regex pattern(R"(010[-.\s]?(\d{4})[-.\s]?(\d{4}))");
// $1, $2๋ ์บก์ฒ ๊ทธ๋ฃน์ ์๋ฏธ (๊ดํธ๋ก ๋ฌถ์ธ ๋ถ๋ถ)
std::string formatted = std::regex_replace(
text,
pattern,
"010-$1-$2"
);
return formatted;
}
int main() {
std::string text = "์ฐ๋ฝ์ฒ: 01012345678, 010.9876.5432, 010-1111-2222";
std::cout << "์๋ณธ: " << text << std::endl;
std::cout << "๋ณํ: " << formatPhoneNumber(text) << std::endl;
// ์ถ๋ ฅ:
// ์๋ณธ: ์ฐ๋ฝ์ฒ: 01012345678, 010.9876.5432, 010-1111-2222
// ๋ณํ: ์ฐ๋ฝ์ฒ: 010-1234-5678, 010-9876-5432, 010-1111-2222
return 0;
}
๐ก ์บก์ฒ ๊ทธ๋ฃน ํ์ฉ๋ฒ! ๊ดํธ ()๋ก ๋ฌถ์ธ ๋ถ๋ถ์ ์บก์ฒ ๊ทธ๋ฃน์ด ๋ผ. $1, $2๋ก ์ฐธ์กฐํ ์ ์์ด์ ํจํด์ ์ผ๋ถ๋ง ์ถ์ถํ๊ฑฐ๋ ์ฌ๋ฐฐ์นํ ๋ ์์ฒญ ์ ์ฉํด!
๐ ๋น๋ฐ๋ฒํธ ๊ฐ๋ ๊ฒ์ฆ
๋ณด์์ด ์ค์ํ ์๋! ๋น๋ฐ๋ฒํธ๊ฐ ์ถฉ๋ถํ ๊ฐ๋ ฅํ์ง ๊ฒ์ฆํ๋ ์ฝ๋๋ฅผ ๋ง๋ค์ด๋ณด์:
#include <iostream>
#include <regex>
#include <string>
struct PasswordStrength {
bool hasMinLength;
bool hasUpperCase;
bool hasLowerCase;
bool hasDigit;
bool hasSpecialChar;
bool isStrong() const {
return hasMinLength && hasUpperCase &&
hasLowerCase && hasDigit && hasSpecialChar;
}
};
PasswordStrength checkPassword(const std::string& password) {
PasswordStrength strength;
// ์ต์ 8์ ์ด์
strength.hasMinLength = password.length() >= 8;
// ๋๋ฌธ์ ํฌํจ
strength.hasUpperCase = std::regex_search(password, std::regex("[A-Z]"));
// ์๋ฌธ์ ํฌํจ
strength.hasLowerCase = std::regex_search(password, std::regex("[a-z]"));
// ์ซ์ ํฌํจ
strength.hasDigit = std::regex_search(password, std::regex(R"(\d)"));
// ํน์๋ฌธ์ ํฌํจ
strength.hasSpecialChar = std::regex_search(
password,
std::regex(R"([!@#$%^&*()_+\-=\[\]{};':"\\|,.<>/?])")
);
return strength;
}
void printPasswordAnalysis(const std::string& password) {
auto strength = checkPassword(password);
std::cout << "๋น๋ฐ๋ฒํธ: " << password << std::endl;
std::cout << "๊ธธ์ด (8์ ์ด์): " << (strength.hasMinLength ? "โ
" : "โ") << std::endl;
std::cout << "๋๋ฌธ์ ํฌํจ: " << (strength.hasUpperCase ? "โ
" : "โ") << std::endl;
std::cout << "์๋ฌธ์ ํฌํจ: " << (strength.hasLowerCase ? "โ
" : "โ") << std::endl;
std::cout << "์ซ์ ํฌํจ: " << (strength.hasDigit ? "โ
" : "โ") << std::endl;
std::cout << "ํน์๋ฌธ์ ํฌํจ: " << (strength.hasSpecialChar ? "โ
" : "โ") << std::endl;
std::cout << "๊ฐ๋: " << (strength.isStrong() ? "๐ ๊ฐํจ" : "โ ๏ธ ์ฝํจ") << std::endl;
std::cout << "---" << std::endl;
}
int main() {
printPasswordAnalysis("password"); // ์ฝํจ
printPasswordAnalysis("Password123"); // ์ฝํจ (ํน์๋ฌธ์ ์์)
printPasswordAnalysis("Pass123!"); // ์ฝํจ (8์ ๋ฏธ๋ง)
printPasswordAnalysis("Password123!"); // ๊ฐํจ!
return 0;
}
๐ฏ ๊ณ ๊ธ ๊ธฐ๋ฅ: regex_iterator์ smatch
ํ ๋ฌธ์์ด์์ ์ฌ๋ฌ ๊ฐ์ ๋งค์นญ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ์์ผ ํ ๋๊ฐ ์์ง? ๊ทธ๋ด ๋๋ regex_iterator๋ฅผ ์ฌ์ฉํ๋ฉด ๋ผ! ๐
๐ ๋ชจ๋ ๋งค์นญ ๊ฒฐ๊ณผ ์ํํ๊ธฐ
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string text = "์ด๋ฉ์ผ ๋ชฉ๋ก: user1@test.com, admin@example.com, info@company.co.kr";
std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
// regex_iterator ์์ฑ
auto words_begin = std::sregex_iterator(text.begin(), text.end(), pattern);
auto words_end = std::sregex_iterator();
int count = 0;
std::cout << "๋ฐ๊ฒฌ๋ ์ด๋ฉ์ผ ์ฃผ์๋ค:" << std::endl;
for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
std::smatch match = *i;
std::cout << ++count << ". " << match.str() << std::endl;
}
std::cout << "์ด " << count << "๊ฐ์ ์ด๋ฉ์ผ์ ์ฐพ์์ด์! ๐ง" << std::endl;
return 0;
}
// ์ถ๋ ฅ:
// ๋ฐ๊ฒฌ๋ ์ด๋ฉ์ผ ์ฃผ์๋ค:
// 1. user1@test.com
// 2. admin@example.com
// 3. info@company.co.kr
// ์ด 3๊ฐ์ ์ด๋ฉ์ผ์ ์ฐพ์์ด์! ๐ง
๐ฆ smatch๋ก ์์ธ ์ ๋ณด ์ถ์ถํ๊ธฐ
smatch๋ ๋งค์นญ ๊ฒฐ๊ณผ์ ๋ํ ์์ธํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ด. ์บก์ฒ ๊ทธ๋ฃน๋ณ๋ก ์ ๊ทผํ ์ ์์ด์ ์ ๋ง ์ ์ฉํด!
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string text = "์๋
์์ผ: 1990-05-15";
// ์บก์ฒ ๊ทธ๋ฃน์ผ๋ก ๋
, ์, ์ผ์ ๋ถ๋ฆฌ
std::regex pattern(R"((\d{4})-(\d{2})-(\d{2}))");
std::smatch match;
if (std::regex_search(text, match, pattern)) {
std::cout << "์ ์ฒด ๋งค์นญ: " << match.str(0) << std::endl;
std::cout << "๋
๋: " << match.str(1) << std::endl;
std::cout << "์: " << match.str(2) << std::endl;
std::cout << "์ผ: " << match.str(3) << std::endl;
// ์ถ๊ฐ ์ ๋ณด
std::cout << "\n๋งค์นญ ์์น: " << match.position() << std::endl;
std::cout << "๋งค์นญ ๊ธธ์ด: " << match.length() << std::endl;
std::cout << "๋งค์นญ ์ ๋ฌธ์์ด: " << match.prefix() << std::endl;
std::cout << "๋งค์นญ ํ ๋ฌธ์์ด: " << match.suffix() << std::endl;
}
return 0;
}
// ์ถ๋ ฅ:
// ์ ์ฒด ๋งค์นญ: 1990-05-15
// ๋
๋: 1990
// ์: 05
// ์ผ: 15
//
// ๋งค์นญ ์์น: 7
// ๋งค์นญ ๊ธธ์ด: 10
// ๋งค์นญ ์ ๋ฌธ์์ด: ์๋
์์ผ:
// ๋งค์นญ ํ ๋ฌธ์์ด:
๐ smatch ์ฃผ์ ๋ฉ์๋:
โข str(n) - n๋ฒ์งธ ์บก์ฒ ๊ทธ๋ฃน์ ๋ฌธ์์ด (0์ ์ ์ฒด ๋งค์นญ)
โข position(n) - n๋ฒ์งธ ์บก์ฒ ๊ทธ๋ฃน์ ์์ ์์น
โข length(n) - n๋ฒ์งธ ์บก์ฒ ๊ทธ๋ฃน์ ๊ธธ์ด
โข prefix() - ๋งค์นญ ์ด์ ์ ๋ฌธ์์ด
โข suffix() - ๋งค์นญ ์ดํ์ ๋ฌธ์์ด
โข size() - ์บก์ฒ ๊ทธ๋ฃน์ ๊ฐ์ (์ ์ฒด ๋งค์นญ ํฌํจ)
โก ์ฑ๋ฅ ์ต์ ํ ํ
์ ๊ทํํ์์ ๊ฐ๋ ฅํ์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ด. ์ค์ ์์ ์ ์ฉํ ์ต์ ํ ํ๋ค์ ์๋ ค์ค๊ฒ! ๐
1๏ธโฃ ์ ๊ทํํ์ ๊ฐ์ฒด ์ฌ์ฌ์ฉํ๊ธฐ
โ ๏ธ ๋นํจ์จ์ ์ธ ์ฝ๋:
// ๋์ ์: ๋งค๋ฒ regex ๊ฐ์ฒด๋ฅผ ์์ฑ
for (const auto& text : texts) {
std::regex pattern(R"(\d+)"); // ๋ฐ๋ณต๋ฌธ๋ง๋ค ์ปดํ์ผ! ๐ฑ
if (std::regex_search(text, pattern)) {
// ...
}
}
โ ํจ์จ์ ์ธ ์ฝ๋:
// ์ข์ ์: regex ๊ฐ์ฒด๋ฅผ ํ ๋ฒ๋ง ์์ฑ
std::regex pattern(R"(\d+)"); // ํ ๋ฒ๋ง ์ปดํ์ผ! ๐
for (const auto& text : texts) {
if (std::regex_search(text, pattern)) {
// ...
}
}
์ ๊ทํํ์ ํจํด์ ์ปดํ์ผํ๋ ๊ฑด ๋น์ฉ์ด ํฐ ์์ ์ด์ผ. ๊ฐ์ ํจํด์ ์ฌ๋ฌ ๋ฒ ์ฌ์ฉํ๋ค๋ฉด ๋ฐ๋์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฌ์ฉํด์ผ ํด!
2๏ธโฃ ์ ์ ํ ํจ์ ์ ํํ๊ธฐ
regex_match - ์ ์ฒด ๋ฌธ์์ด์ด ํจํด๊ณผ ์ผ์นํ๋์ง๋ง ํ์ธํ ๋ (๊ฐ์ฅ ๋น ๋ฆ)
regex_search - ๋ฌธ์์ด ๋ด์์ ํจํด์ ์ฐพ์ ๋
regex_iterator - ๋ชจ๋ ๋งค์นญ์ ์ฐพ์์ผ ํ ๋
std::string input = "12345";
// ์ ์ฒด๊ฐ ์ซ์์ธ์ง๋ง ํ์ธํ๋ฉด ๋๋ ๊ฒฝ์ฐ
if (std::regex_match(input, std::regex(R"(^\d+$)"))) {
// regex_match๊ฐ regex_search๋ณด๋ค ๋น ๋ฆ!
}
// ์ซ์๊ฐ ํฌํจ๋์ด ์๋์ง ํ์ธํ๋ ๊ฒฝ์ฐ
if (std::regex_search(input, std::regex(R"(\d+)"))) {
// ์ด ๊ฒฝ์ฐ๋ regex_search ์ฌ์ฉ
}
3๏ธโฃ ํ์์ vs ๊ฒ์ผ๋ฅธ ์๋์
์๋์์ ํ์์ฑ(greedy)์ ์ดํดํ๋ฉด ์ฑ๋ฅ๊ณผ ์ ํ์ฑ์ ๋ชจ๋ ์ก์ ์ ์์ด!
ํ์์ ์๋์ (Greedy): ๊ฐ๋ฅํ ํ ๋ง์ด ๋งค์นญ
โข *, +, {n,}
๊ฒ์ผ๋ฅธ ์๋์ (Lazy): ๊ฐ๋ฅํ ํ ์ ๊ฒ ๋งค์นญ
โข *?, +?, {n,}?
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string html = "<div>์ฒซ๋ฒ์งธ</div><div>๋๋ฒ์งธ</div>";
// ํ์์ : ๊ฐ๋ฅํ ํ ๋ง์ด ๋งค์นญ
std::regex greedy(R"(<div>.*</div>)");
std::smatch match1;
if (std::regex_search(html, match1, greedy)) {
std::cout << "ํ์์ : " << match1.str() << std::endl;
// ์ถ๋ ฅ: <div>์ฒซ๋ฒ์งธ</div><div>๋๋ฒ์งธ</div> (์ ์ฒด๋ฅผ ๋งค์นญ!)
}
// ๊ฒ์ผ๋ฅธ: ๊ฐ๋ฅํ ํ ์ ๊ฒ ๋งค์นญ
std::regex lazy(R"(<div>.*?</div>)");
std::smatch match2;
if (std::regex_search(html, match2, lazy)) {
std::cout << "๊ฒ์ผ๋ฅธ: " << match2.str() << std::endl;
// ์ถ๋ ฅ: <div>์ฒซ๋ฒ์งธ</div> (์ฒซ ๋ฒ์งธ๋ง ๋งค์นญ!)
}
return 0;
}
๐ก HTML/XML ํ์ฑํ ๋๋ ๊ฒ์ผ๋ฅธ ์๋์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ผ๋ฐ์ ์ด์ผ. ํ์ง๋ง ๋ณต์กํ HTML์ ์ ๊ทํํ์๋ณด๋ค ์ ์ฉ ํ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ข์!
4๏ธโฃ ์ปดํ์ผ ์ต์ ํ์ฉํ๊ธฐ
std::regex๋ ๋ค์ํ ์ปดํ์ผ ์ต์ ์ ์ ๊ณตํด. ์ํฉ์ ๋ง๊ฒ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ๊ณผ ๊ธฐ๋ฅ์ ์ต์ ํํ ์ ์์ด!
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string text = "Hello WORLD";
// ๊ธฐ๋ณธ: ๋์๋ฌธ์ ๊ตฌ๋ถ
std::regex pattern1("hello");
std::cout << std::regex_search(text, pattern1) << std::endl; // 0 (false)
// icase: ๋์๋ฌธ์ ๋ฌด์
std::regex pattern2("hello", std::regex::icase);
std::cout << std::regex_search(text, pattern2) << std::endl; // 1 (true)
// optimize: ์ฑ๋ฅ ์ต์ ํ (์ปดํ์ผ ์๊ฐ์ ๋์ด๋์ง๋ง ์คํ ์๋ ํฅ์)
std::regex pattern3(R"(\d+)", std::regex::optimize);
// ECMAScript (๊ธฐ๋ณธ), extended, awk, grep, egrep ๋ฑ ๋ฌธ๋ฒ ์ ํ ๊ฐ๋ฅ
std::regex pattern4(R"(\d+)", std::regex::extended);
return 0;
}
| ์ต์ | ์ค๋ช | ์ฌ์ฉ ์๋๋ฆฌ์ค |
|---|---|---|
| icase | ๋์๋ฌธ์ ๋ฌด์ | ์ฌ์ฉ์ ์ ๋ ฅ ๊ฒ์ฆ |
| optimize | ์คํ ์๋ ์ต์ ํ | ๊ฐ์ ํจํด์ ๋ง์ด ์ฌ์ฉํ ๋ |
| nosubs | ์บก์ฒ ๊ทธ๋ฃน ๋ฌด์ | ๋งค์นญ ์ฌ๋ถ๋ง ํ์ธํ ๋ |
| multiline | ^์ $๊ฐ ๊ฐ ์ค์ ์ ์ฉ | ์ฌ๋ฌ ์ค ํ ์คํธ ์ฒ๋ฆฌ |
๐จ ์ค์ ํ๋ก์ ํธ: ๋ก๊ทธ ํ์ผ ๋ถ์๊ธฐ
์ด์ ๋ฐฐ์ด ๋ด์ฉ์ ์ข ํฉํด์ ์ค์ฉ์ ์ธ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณด์! ์๋ฒ ๋ก๊ทธ ํ์ผ์ ๋ถ์ํ๋ ํ๋ก๊ทธ๋จ์ด์ผ. ๐
#include <iostream>
#include <regex>
#include <string>
#include <vector>
#include <map>
#include <fstream>
struct LogEntry {
std::string timestamp;
std::string level;
std::string ip;
std::string message;
};
class LogAnalyzer {
private:
// ๋ก๊ทธ ํจํด: [2024-01-15 10:30:45] ERROR 192.168.1.1 - Connection failed
std::regex logPattern{
R"(\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+) ([\d.]+) - (.+))"
};
std::vector<LogEntry> logs;
std::map<std::string, int> levelCount;
std::map<std::string, int> ipCount;
public:
void parseLine(const std::string& line) {
std::smatch match;
if (std::regex_search(line, match, logPattern)) {
LogEntry entry;
entry.timestamp = match.str(1);
entry.level = match.str(2);
entry.ip = match.str(3);
entry.message = match.str(4);
logs.push_back(entry);
levelCount[entry.level]++;
ipCount[entry.ip]++;
}
}
void parseFile(const std::string& filename) {
std::ifstream file(filename);
std::string line;
while (std::getline(file, line)) {
parseLine(line);
}
}
void printStatistics() {
std::cout << "๐ ๋ก๊ทธ ๋ถ์ ๊ฒฐ๊ณผ\n" << std::endl;
std::cout << "์ด ๋ก๊ทธ ์: " << logs.size() << std::endl;
std::cout << "\n๋ก๊ทธ ๋ ๋ฒจ๋ณ ํต๊ณ:" << std::endl;
for (const auto& [level, count] : levelCount) {
std::cout << " " << level << ": " << count << "๊ฑด" << std::endl;
}
std::cout << "\nIP๋ณ ์ ์ ํต๊ณ (์์ 5๊ฐ):" << std::endl;
std::vector<std::pair<std::string, int>> sortedIPs(ipCount.begin(), ipCount.end());
std::sort(sortedIPs.begin(), sortedIPs.end(),
[](const auto& a, const auto& b) { return a.second > b.second; });
int count = 0;
for (const auto& [ip, cnt] : sortedIPs) {
if (++count > 5) break;
std::cout << " " << ip << ": " << cnt << "ํ" << std::endl;
}
}
std::vector<LogEntry> findErrorsFromIP(const std::string& ip) {
std::vector<LogEntry> errors;
for (const auto& log : logs) {
if (log.ip == ip && log.level == "ERROR") {
errors.push_back(log);
}
}
return errors;
}
std::vector<LogEntry> findByTimeRange(
const std::string& startTime,
const std::string& endTime
) {
std::vector<LogEntry> results;
for (const auto& log : logs) {
if (log.timestamp >= startTime && log.timestamp <= endTime) {
results.push_back(log);
}
}
return results;
}
};
int main() {
LogAnalyzer analyzer;
// ์ํ ๋ก๊ทธ ๋ฐ์ดํฐ
std::vector<std::string> sampleLogs = {
"[2024-01-15 10:30:45] INFO 192.168.1.100 - User login successful",
"[2024-01-15 10:31:20] ERROR 192.168.1.100 - Database connection failed",
"[2024-01-15 10:32:15] INFO 192.168.1.101 - Page loaded",
"[2024-01-15 10:33:00] WARNING 192.168.1.102 - High memory usage",
"[2024-01-15 10:34:30] ERROR 192.168.1.100 - Timeout occurred",
"[2024-01-15 10:35:45] INFO 192.168.1.103 - File uploaded",
"[2024-01-15 10:36:20] ERROR 192.168.1.101 - Invalid request"
};
// ๋ก๊ทธ ํ์ฑ
for (const auto& log : sampleLogs) {
analyzer.parseLine(log);
}
// ํต๊ณ ์ถ๋ ฅ
analyzer.printStatistics();
// ํน์ IP์ ์๋ฌ ์ฐพ๊ธฐ
std::cout << "\n๐ 192.168.1.100์ ์๋ฌ ๋ก๊ทธ:" << std::endl;
auto errors = analyzer.findErrorsFromIP("192.168.1.100");
for (const auto& error : errors) {
std::cout << " [" << error.timestamp << "] "
<< error.message << std::endl;
}
return 0;
}
์ด ๋ก๊ทธ ๋ถ์๊ธฐ๋ ์ค์ ์๋ฒ ๊ด๋ฆฌ์์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ด! ์ ๊ทํํ์์ผ๋ก ๋ก๊ทธ ํ์์ ํ์ฑํ๊ณ , ํต๊ณ๋ฅผ ๋ด๊ณ , ํน์ ์กฐ๊ฑด์ ๋ก๊ทธ๋ฅผ ์ฐพ์ ์ ์์ง. ๐
๐ ์ค์ ํ์ฉ: URL ํ์ฑ๊ณผ ๊ฒ์ฆ
์น ๊ฐ๋ฐ์์ ๋น ์ง ์ ์๋ ๊ฒ URL ์ฒ๋ฆฌ์ง! URL์ ํ์ฑํ๊ณ ๊ฒ์ฆํ๋ ์ค์ฉ์ ์ธ ์์ ๋ฅผ ๋ง๋ค์ด๋ณด์. ๐
#include <iostream>
#include <regex>
#include <string>
#include <optional>
struct URL {
std::string protocol;
std::string domain;
std::string port;
std::string path;
std::string query;
std::string fragment;
void print() const {
std::cout << "๐ URL ๋ถ์ ๊ฒฐ๊ณผ:" << std::endl;
std::cout << " ํ๋กํ ์ฝ: " << protocol << std::endl;
std::cout << " ๋๋ฉ์ธ: " << domain << std::endl;
if (!port.empty())
std::cout << " ํฌํธ: " << port << std::endl;
if (!path.empty())
std::cout << " ๊ฒฝ๋ก: " << path << std::endl;
if (!query.empty())
std::cout << " ์ฟผ๋ฆฌ: " << query << std::endl;
if (!fragment.empty())
std::cout << " ํ๋๊ทธ๋จผํธ: " << fragment << std::endl;
}
};
class URLParser {
private:
// URL ํ์ฑ ์ ๊ทํํ์
std::regex urlPattern{
R"(^(https?):\/\/" // ํ๋กํ ์ฝ
R"(([a-zA-Z0-9.-]+)" // ๋๋ฉ์ธ
R"((?::(\d+))?" // ํฌํธ (์ ํ)
R"(([\/\w.-]*)" // ๊ฒฝ๋ก (์ ํ)
R"((?:\?([^#]*))?" // ์ฟผ๋ฆฌ (์ ํ)
R"((?:#(.*))?$)" // ํ๋๊ทธ๋จผํธ (์ ํ)
};
public:
std::optional<URL> parse(const std::string& urlString) {
std::smatch match;
if (!std::regex_match(urlString, match, urlPattern)) {
return std::nullopt;
}
URL url;
url.protocol = match.str(1);
url.domain = match.str(2);
url.port = match.str(3);
url.path = match.str(4);
url.query = match.str(5);
url.fragment = match.str(6);
return url;
}
bool isValidURL(const std::string& urlString) {
return std::regex_match(urlString, urlPattern);
}
std::string extractDomain(const std::string& urlString) {
std::regex domainPattern(R"(https?:\/\/([a-zA-Z0-9.-]+))");
std::smatch match;
if (std::regex_search(urlString, match, domainPattern)) {
return match.str(1);
}
return "";
}
std::map<std::string, std::string> parseQueryString(const std::string& query) {
std::map<std::string, std::string> params;
std::regex paramPattern(R"(([^&=]+)=([^&]*))");
auto begin = std::sregex_iterator(query.begin(), query.end(), paramPattern);
auto end = std::sregex_iterator();
for (auto it = begin; it != end; ++it) {
std::smatch match = *it;
params[match.str(1)] = match.str(2);
}
return params;
}
};
int main() {
URLParser parser;
std::vector<std::string> testURLs = {
"https://www.jaenung.net/knowledge/article?id=123&category=cpp#section2",
"http://example.com:8080/api/users",
"https://github.com/user/repo",
"invalid-url",
"ftp://files.example.com/download"
};
for (const auto& urlString : testURLs) {
std::cout << "\n๋ถ์ ๋์: " << urlString << std::endl;
if (auto url = parser.parse(urlString)) {
url->print();
// ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ ํ์ฑ
if (!url->query.empty()) {
std::cout << "\n ๐ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ:" << std::endl;
auto params = parser.parseQueryString(url->query);
for (const auto& [key, value] : params) {
std::cout << " " << key << " = " << value << std::endl;
}
}
} else {
std::cout << " โ ์ ํจํ์ง ์์ URL์
๋๋ค." << std::endl;
}
std::cout << std::string(50, '-') << std::endl;
}
return 0;
}
์ด URL ํ์๋ ์น ํฌ๋กค๋ฌ๋ API ํด๋ผ์ด์ธํธ๋ฅผ ๋ง๋ค ๋ ์ ๋ง ์ ์ฉํด! ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์๋ URL ๊ฒ์ฆ๊ณผ ํ์ฑ์ ํ์์ ์ธ ๊ธฐ๋ฅ์ด์ง. ๐ฏ
๐ญ ์ ๊ทํํ์ ๋๋ฒ๊น ๊ณผ ํ ์คํธ
์ ๊ทํํ์์ ๊ฐ๋ ฅํ์ง๋ง ๋ณต์กํด์ง์๋ก ๋๋ฒ๊น ์ด ์ด๋ ค์์ ธ. ํจ๊ณผ์ ์ผ๋ก ํ ์คํธํ๊ณ ๋๋ฒ๊น ํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์! ๐ง
๐งช ํ ์คํธ ํ๋ ์์ํฌ ๋ง๋ค๊ธฐ
#include <iostream>
#include <regex>
#include <string>
#include <vector>
class RegexTester {
private:
struct TestCase {
std::string input;
bool shouldMatch;
std::string description;
};
std::string pattern;
std::regex regex;
std::vector<TestCase> testCases;
public:
RegexTester(const std::string& pattern)
: pattern(pattern), regex(pattern) {}
void addTest(const std::string& input, bool shouldMatch,
const std::string& description = "") {
testCases.push_back({input, shouldMatch, description});
}
void runTests() {
std::cout << "๐งช ์ ๊ทํํ์ ํ
์คํธ ์์" << std::endl;
std::cout << "ํจํด: " << pattern << "\n" << std::endl;
int passed = 0;
int failed = 0;
for (size_t i = 0; i < testCases.size(); ++i) {
const auto& test = testCases[i];
bool result = std::regex_match(test.input, regex);
bool success = (result == test.shouldMatch);
if (success) {
std::cout << "โ
ํ
์คํธ " << (i + 1) << " ํต๊ณผ";
passed++;
} else {
std::cout << "โ ํ
์คํธ " << (i + 1) << " ์คํจ";
failed++;
}
std::cout << " - " << test.input;
if (!test.description.empty()) {
std::cout << " (" << test.description << ")";
}
std::cout << std::endl;
if (!success) {
std::cout << " ์์: " << (test.shouldMatch ? "๋งค์นญ" : "๋ถ์ผ์น")
<< ", ์ค์ : " << (result ? "๋งค์นญ" : "๋ถ์ผ์น") << std::endl;
}
}
std::cout << "\n๐ ๊ฒฐ๊ณผ: " << passed << "๊ฐ ํต๊ณผ, "
<< failed << "๊ฐ ์คํจ" << std::endl;
}
void explainPattern() {
std::cout << "\n๐ ํจํด ์ค๋ช
:" << std::endl;
std::cout << pattern << std::endl;
// ์ฌ๊ธฐ์ ํจํด ๋ถ์ ๋ก์ง์ ์ถ๊ฐํ ์ ์์ด
}
};
int main() {
// ์ด๋ฉ์ผ ๊ฒ์ฆ ํ
์คํธ
RegexTester emailTester(R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)");
emailTester.addTest("user@example.com", true, "๊ธฐ๋ณธ ์ด๋ฉ์ผ");
emailTester.addTest("test.user@domain.co.kr", true, "์ ๊ณผ ์๋ธ๋๋ฉ์ธ");
emailTester.addTest("user+tag@example.com", true, "ํ๋ฌ์ค ๊ธฐํธ");
emailTester.addTest("invalid@", false, "๋๋ฉ์ธ ์์");
emailTester.addTest("@invalid.com", false, "์ฌ์ฉ์๋ช
์์");
emailTester.addTest("no-at-sign.com", false, "@๊ธฐํธ ์์");
emailTester.addTest("user@domain", false, "์ต์์ ๋๋ฉ์ธ ์์");
emailTester.runTests();
std::cout << "\n" << std::string(60, '=') << "\n" << std::endl;
// ์ ํ๋ฒํธ ๊ฒ์ฆ ํ
์คํธ
RegexTester phoneTester(R"(^01[0-9]-\d{4}-\d{4}$)");
phoneTester.addTest("010-1234-5678", true, "์ผ๋ฐ ํด๋ํฐ");
phoneTester.addTest("011-9876-5432", true, "011 ๋ฒํธ");
phoneTester.addTest("010-123-5678", false, "์ค๊ฐ ์๋ฆฌ ๋ถ์กฑ");
phoneTester.addTest("02-1234-5678", false, "์ง์ญ๋ฒํธ");
phoneTester.addTest("01012345678", false, "ํ์ดํ ์์");
phoneTester.runTests();
return 0;
}
๐ก ์ค์ ํ: ์ ๊ทํํ์์ ์์ฑํ ๋๋ ํญ์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ํจ๊ป ๋ง๋ค์ด. ํนํ ๊ฒฝ๊ณ ์กฐ๊ฑด(boundary conditions)์ ๊ผญ ํ ์คํธํด์ผ ํด!
๐ ์ผ๋ฐ์ ์ธ ์ค์์ ํด๊ฒฐ๋ฒ
์ค์ 1: ๋ฐฑ์ฌ๋์ ์ด์ค์ผ์ดํ ์๊ธฐ
// โ ์๋ชป๋ ์ฝ๋
std::regex pattern("\d+"); // ์ปดํ์ผ ์๋ฌ ๋๋ ์์๊ณผ ๋ค๋ฅธ ๋์
// โ
์ฌ๋ฐ๋ฅธ ์ฝ๋
std::regex pattern("\\d+"); // ๋ฐฑ์ฌ๋์ ๋ ๋ฒ
// ๋๋
std::regex pattern(R"(\d+)"); // raw string literal ์ฌ์ฉ
์ค์ 2: ํน์ ๋ฌธ์ ์ด์ค์ผ์ดํ ์ ํ๊ธฐ
// โ ์๋ชป๋ ์ฝ๋ - ์ (.)์ ๋ชจ๋ ๋ฌธ์๋ฅผ ์๋ฏธ
std::regex pattern("192.168.1.1"); // "192A168B1C1"๋ ๋งค์นญ๋จ!
// โ
์ฌ๋ฐ๋ฅธ ์ฝ๋
std::regex pattern(R"(192\.168\.1\.1)"); // ์ ์ ๋ฆฌํฐ๋ด๋ก ์ฒ๋ฆฌ
์ค์ 3: regex_match์ regex_search ํผ๋
std::string text = "๋ด ๋ฒํธ๋ 010-1234-5678์ด์ผ";
std::regex pattern(R"(010-\d{4}-\d{4})");
// regex_match: ์ ์ฒด ๋ฌธ์์ด์ด ํจํด๊ณผ ์ผ์นํด์ผ ํจ
std::cout << std::regex_match(text, pattern) << std::endl; // 0 (false)
// regex_search: ๋ฌธ์์ด ๋ด์์ ํจํด์ ์ฐพ์
std::cout << std::regex_search(text, pattern) << std::endl; // 1 (true)
๐ก๏ธ ๋ณด์๊ณผ ์ฑ๋ฅ: ReDoS ๊ณต๊ฒฉ ๋ฐฉ์ดํ๊ธฐ
์ ๊ทํํ์์ ๊ฐ๋ ฅํ์ง๋ง, ์๋ชป ์์ฑํ๋ฉด ReDoS(Regular Expression Denial of Service) ๊ณต๊ฒฉ์ ์ทจ์ฝํด์ง ์ ์์ด. ์ด๊ฑด ์ ๋ง ์ค์ํ ๋ณด์ ์ด์์ผ! ๐จ
โ ๏ธ ์ํํ ํจํด์ ์
์ํํ ํจํด: ์ค์ฒฉ๋ ์๋์
// โ ์ํํ ํจํด - ๋ฐฑํธ๋ํน์ด ๊ธฐํ๊ธ์์ ์ผ๋ก ์ฆ๊ฐ
std::regex dangerous(R"((a+)+b)");
// ์ด ์
๋ ฅ์ ์์ฒญ๋ ์๊ฐ์ด ๊ฑธ๋ฆผ (ReDoS ๊ณต๊ฒฉ!)
std::string malicious = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa!";
// 'b'๊ฐ ์์ด์ ๋ชจ๋ ์กฐํฉ์ ์๋ํ๊ฒ ๋จ
โ ์์ ํ ํจํด์ผ๋ก ๊ฐ์
// โ
์์ ํ ํจํด - ์ค์ฒฉ ์ ๊ฑฐ
std::regex safe(R"(a+b)");
// ๋๋ ์์ ์๋์ ์ฌ์ฉ (C++์์๋ ์ ํ์ )
std::regex safer(R"(a++b)"); // ๋ฐฑํธ๋ํน ์์
๐ ์์ ํ ์ ๊ทํํ์ ์์ฑ ๊ฐ์ด๋
1. ์ค์ฒฉ๋ ์๋์ ํผํ๊ธฐ
โข (a+)+, (a*)* ๊ฐ์ ํจํด์ ์ํ
โข ๊ฐ๋ฅํ๋ฉด ๋จ์ผ ์๋์๋ก ํํ: a+
2. ๊ต๋(alternation) ์ต์ ํ
โข (a|a)* ๊ฐ์ ์ค๋ณต ํผํ๊ธฐ
โข ๊ณตํต ๋ถ๋ถ์ ์์ผ๋ก: (abc|abd) โ ab(c|d)
3. ์ ๋ ฅ ๊ธธ์ด ์ ํ
โข ์ฌ์ฉ์ ์ ๋ ฅ์ ํญ์ ๊ธธ์ด ๊ฒ์ฆ
โข ํฉ๋ฆฌ์ ์ธ ์ต๋ ๊ธธ์ด ์ค์
4. ํ์์์ ์ค์ ๊ณ ๋ ค
โข ์ฅ์๊ฐ ์คํ๋๋ ์ ๊ทํํ์ ๊ฐ์ง
โข ๋ณ๋ ์ค๋ ๋์์ ์คํํ๊ณ ํ์์์ ์ ์ฉ
#include <iostream>
#include <regex>
#include <string>
#include <chrono>
#include <future>
class SafeRegex {
private:
std::regex pattern;
std::chrono::milliseconds timeout;
size_t maxInputLength;
public:
SafeRegex(const std::string& pattern,
std::chrono::milliseconds timeout = std::chrono::milliseconds(1000),
size_t maxInputLength = 10000)
: pattern(pattern), timeout(timeout), maxInputLength(maxInputLength) {}
bool safeMatch(const std::string& input) {
// ์
๋ ฅ ๊ธธ์ด ๊ฒ์ฆ
if (input.length() > maxInputLength) {
std::cerr << "โ ๏ธ ์
๋ ฅ์ด ๋๋ฌด ๊น๋๋ค!" << std::endl;
return false;
}
// ํ์์์์ ์ ์ฉํ ๋งค์นญ
auto future = std::async(std::launch::async, [this, &input]() {
return std::regex_match(input, this->pattern);
});
if (future.wait_for(timeout) == std::future_status::timeout) {
std::cerr << "โฑ๏ธ ์ ๊ทํํ์ ์คํ ์๊ฐ ์ด๊ณผ!" << std::endl;
return false;
}
return future.get();
}
// ํจํด์ ์ํ๋ ๊ฐ๋จํ ์ฒดํฌ
static bool isDangerousPattern(const std::string& pattern) {
// ์ค์ฒฉ๋ ์๋์ ํจํด ๊ฐ์ง
std::regex nested(R"(\([^)]*[+*]\)[+*])");
if (std::regex_search(pattern, nested)) {
std::cout << "โ ๏ธ ๊ฒฝ๊ณ : ์ค์ฒฉ๋ ์๋์๊ฐ ๊ฐ์ง๋์์ต๋๋ค!" << std::endl;
return true;
}
return false;
}
};
int main() {
// ์ํํ ํจํด ์ฒดํฌ
std::string dangerousPattern = R"((a+)+b)";
SafeRegex::isDangerousPattern(dangerousPattern);
// ์์ ํ ์ ๊ทํํ์ ์ฌ์ฉ
SafeRegex safeRegex(R"(^[a-zA-Z0-9]+$)", std::chrono::milliseconds(100));
std::cout << "ํ
์คํธ 1: " << safeRegex.safeMatch("abc123") << std::endl;
std::cout << "ํ
์คํธ 2: " << safeRegex.safeMatch("abc-123") << std::endl;
// ๋๋ฌด ๊ธด ์
๋ ฅ ํ
์คํธ
std::string longInput(20000, 'a');
std::cout << "ํ
์คํธ 3: " << safeRegex.safeMatch(longInput) << std::endl;
return 0;
}
๐จ ์ค์ ํ๋ก์ ํธ: ๋งํฌ๋ค์ด ํ์ ๋ง๋ค๊ธฐ
์ด์ ์ ๋ง ์ค์ฉ์ ์ธ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณด์! ๊ฐ๋จํ ๋งํฌ๋ค์ด ํ์๋ฅผ ์ ๊ทํํ์์ผ๋ก ๊ตฌํํด๋ณผ๊ฒ. ๐
#include <iostream>
#include <regex>
#include <string>
#include <sstream>
class MarkdownParser {
private:
// ๋ค์ํ ๋งํฌ๋ค์ด ํจํด๋ค
std::regex headerPattern{R"(^(#{1,6})\s+(.+)$)"};
std::regex boldPattern{R"(\*\*(.+?)\*\*)"};
std::regex italicPattern{R"(\*(.+?)\*)"};
std::regex codePattern{R"(`(.+?)`)"};
std::regex linkPattern{R"(\[([^\]]+)\]\(([^)]+)\))"};
std::regex imagePattern{R"(!\[([^\]]*)\]\(([^)]+)\))"};
std::regex listPattern{R"(^[\*\-]\s+(.+)$)"};
std::regex blockquotePattern{R"(^>\s+(.+)$)"};
public:
std::string parseHeader(const std::string& line) {
std::smatch match;
if (std::regex_match(line, match, headerPattern)) {
int level = match.str(1).length();
std::string content = match.str(2);
return "<h" + std::to_string(level) + ">" +
content + "</h" + std::to_string(level) + ">";
}
return line;
}
std::string parseInline(const std::string& text) {
std::string result = text;
// ๋ณผ๋ ์ฒ๋ฆฌ
result = std::regex_replace(result, boldPattern, "<strong>$1</strong>");
// ์ดํค๋ฆญ ์ฒ๋ฆฌ
result = std::regex_replace(result, italicPattern, "<em>$1</em>");
// ์ฝ๋ ์ฒ๋ฆฌ
result = std::regex_replace(result, codePattern, "<code>$1</code>");
// ๋งํฌ ์ฒ๋ฆฌ
result = std::regex_replace(result, linkPattern,
"<a href=\"$2\">$1</a>");
// ์ด๋ฏธ์ง ์ฒ๋ฆฌ
result = std::regex_replace(result, imagePattern,
"<img src=\"$2\" alt=\"$1\" />");
return result;
}
std::string parseList(const std::string& line) {
std::smatch match;
if (std::regex_match(line, match, listPattern)) {
return "<li>" + parseInline(match.str(1)) + "</li>";
}
return line;
}
std::string parseBlockquote(const std::string& line) {
std::smatch match;
if (std::regex_match(line, match, blockquotePattern)) {
return "<blockquote>" + parseInline(match.str(1)) + "</blockquote>";
}
return line;
}
std::string parse(const std::string& markdown) {
std::istringstream stream(markdown);
std::string line;
std::string html;
bool inList = false;
while (std::getline(stream, line)) {
if (line.empty()) {
if (inList) {
html += "</ul>\n";
inList = false;
}
html += "<br>\n";
continue;
}
// ํค๋ ์ฒดํฌ
std::string parsed = parseHeader(line);
if (parsed != line) {
if (inList) {
html += "</ul>\n";
inList = false;
}
html += parsed + "\n";
continue;
}
// ๋ฆฌ์คํธ ์ฒดํฌ
parsed = parseList(line);
if (parsed != line) {
if (!inList) {
html += "<ul>\n";
inList = true;
}
html += parsed + "\n";
continue;
}
// ์ธ์ฉ๊ตฌ ์ฒดํฌ
parsed = parseBlockquote(line);
if (parsed != line) {
if (inList) {
html += "</ul>\n";
inList = false;
}
html += parsed + "\n";
continue;
}
// ์ผ๋ฐ ํ
์คํธ
if (inList) {
html += "</ul>\n";
inList = false;
}
html += "<p>" + parseInline(line) + "</p>\n";
}
if (inList) {
html += "</ul>\n";
}
return html;
}
};
int main() {
MarkdownParser parser;
std::string markdown = R"(# ์ฌ๋ฅ๋ท์์ ๋ฐฐ์ฐ๋ C++ ์ ๊ทํํ์
## ์๊ฐ
**์ ๊ทํํ์**์ *ํ
์คํธ ์ฒ๋ฆฌ*์ ๊ฐ๋ ฅํ ๋๊ตฌ์
๋๋ค.
### ์ฃผ์ ๊ธฐ๋ฅ
- ํจํด ๋งค์นญ
- ํ
์คํธ ์ถ์ถ
- ๋ฌธ์์ด ์นํ
> ์ ๊ทํํ์์ ๋ง์คํฐํ๋ฉด ํ
์คํธ ์ฒ๋ฆฌ๊ฐ ์ ๋ง ์ฌ์์ ธ์!
์์ธํ ๋ด์ฉ์ [์ฌ๋ฅ๋ท](https://www.jaenung.net)์์ ํ์ธํ์ธ์.
์ฝ๋ ์์ : `std::regex pattern(R"(\d+)")`
)";
std::cout << "=== ๋งํฌ๋ค์ด ์๋ณธ ===" << std::endl;
std::cout << markdown << std::endl;
std::cout << "\n=== HTML ๋ณํ ๊ฒฐ๊ณผ ===" << std::endl;
std::cout << parser.parse(markdown) << std::endl;
return 0;
}
์ด ๋งํฌ๋ค์ด ํ์๋ ์ค์ ๋ก ์ฌ์ฉํ ์ ์๋ ์์ค์ด์ผ! ๋ฌผ๋ก ์์ ํ ๋งํฌ๋ค์ด ํ์๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ ๋ง์ ๊ธฐ๋ฅ์ด ํ์ํ์ง๋ง, ์ ๊ทํํ์์ ํ์ฉ๋ฒ์ ๋ฐฐ์ฐ๊ธฐ์ ์๋ฒฝํ ์์ ์ง. ๐
๐ ์ค์ ํ์ฉ: ๋ฏผ๊ฐ์ ๋ณด ๋ง์คํน
๊ฐ์ธ์ ๋ณด ๋ณดํธ๊ฐ ์ค์ํ ์๋! ๋ก๊ทธ๋ ์ถ๋ ฅ์์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ์๋์ผ๋ก ๋ง์คํนํ๋ ์ ํธ๋ฆฌํฐ๋ฅผ ๋ง๋ค์ด๋ณด์. ๐
#include <iostream>
#include <regex>
#include <string>
#include <map>
class SensitiveDataMasker {
private:
struct MaskRule {
std::regex pattern;
std::function<std::string(const std::smatch&)> replacer;
};
std::vector<MaskRule> rules;
public:
SensitiveDataMasker() {
// ์ด๋ฉ์ผ ๋ง์คํน: user@example.com โ u***@example.com
rules.push_back({
std::regex(R"(([a-zA-Z0-9])[a-zA-Z0-9._%+-]*@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,}))"),
[](const std::smatch& m) {
return m.str(1) + "***@" + m.str(2);
}
});
// ์ ํ๋ฒํธ ๋ง์คํน: 010-1234-5678 โ 010-****-5678
rules.push_back({
std::regex(R"((01[0-9])-(\d{4})-(\d{4}))"),
[](const std::smatch& m) {
return m.str(1) + "-****-" + m.str(3);
}
});
// ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ ๋ง์คํน: 123456-1234567 โ 123456-*******
rules.push_back({
std::regex(R"((\d{6})-(\d{7}))"),
[](const std::smatch& m) {
return m.str(1) + "-*******";
}
});
// ์ ์ฉ์นด๋ ๋ฒํธ ๋ง์คํน: 1234-5678-9012-3456 โ ****-****-****-3456
rules.push_back({
std::regex(R"((\d{4})-(\d{4})-(\d{4})-(\d{4}))"),
[](const std::smatch& m) {
return "****-****-****-" + m.str(4);
}
});
// IP ์ฃผ์ ๋ง์คํน: 192.168.1.100 โ 192.168.*.*
rules.push_back({
std::regex(R"((\d{1,3}\.\d{1,3})\.\d{1,3}\.\d{1,3})"),
[](const std::smatch& m) {
return m.str(1) + ".*.*";
}
});
}
std::string mask(const std::string& text) {
std::string result = text;
for (const auto& rule : rules) {
std::string temp;
auto begin = std::sregex_iterator(result.begin(), result.end(), rule.pattern);
auto end = std::sregex_iterator();
size_t lastPos = 0;
for (auto it = begin; it != end; ++it) {
const std::smatch& match = *it;
temp += result.substr(lastPos, match.position() - lastPos);
temp += rule.replacer(match);
lastPos = match.position() + match.length();
}
temp += result.substr(lastPos);
result = temp;
}
return result;
}
void addCustomRule(const std::string& pattern,
std::function<std::string(const std::smatch&)> replacer) {
rules.push_back({std::regex(pattern), replacer});
}
};
int main() {
SensitiveDataMasker masker;
std::vector<std::string> testData = {
"์ฌ์ฉ์ ์ด๋ฉ์ผ: john.doe@example.com",
"์ฐ๋ฝ์ฒ: 010-1234-5678",
"์ฃผ๋ฏผ๋ฒํธ: 901234-1234567",
"์นด๋๋ฒํธ: 1234-5678-9012-3456",
"์ ์ IP: 192.168.1.100",
"๋ณตํฉ ์ ๋ณด: user@test.com, 010-9876-5432, 192.168.0.50"
};
std::cout << "๐ ๋ฏผ๊ฐ์ ๋ณด ๋ง์คํน ๊ฒฐ๊ณผ\n" << std::endl;
for (const auto& data : testData) {
std::cout << "์๋ณธ: " << data << std::endl;
std::cout << "๋ง์คํน: " << masker.mask(data) << std::endl;
std::cout << std::string(60, '-') << std::endl;
}
// ์ปค์คํ
๊ท์น ์ถ๊ฐ ์์
masker.addCustomRule(
R"(๋น๋ฐ๋ฒํธ:\s*(\S+))",
[](const std::smatch& m) {
return "๋น๋ฐ๋ฒํธ: ********";
}
);
std::string passwordLog = "๋ก๊ทธ์ธ ์๋ - ๋น๋ฐ๋ฒํธ: MySecret123!";
std::cout << "\n์ปค์คํ
๊ท์น ํ
์คํธ:" << std::endl;
std::cout << "์๋ณธ: " << passwordLog << std::endl;
std::cout << "๋ง์คํน: " << masker.mask(passwordLog) << std::endl;
return 0;
}
๐ก ์ค์ ํ์ฉ: ์ด๋ฐ ๋ง์คํน ์ ํธ๋ฆฌํฐ๋ ๋ก๊น ์์คํ , ๋๋ฒ๊ทธ ์ถ๋ ฅ, ์๋ฌ ๋ฆฌํฌํธ ๋ฑ์์ ํ์์ ์ด์ผ. GDPR ๊ฐ์ ๊ฐ์ธ์ ๋ณด ๋ณดํธ ๊ท์ ์ ์ค์ํ๋ ๋ฐ๋ ์ค์ํ์ง!
๐ ์ ๊ทํํ์ ์นํธ์ํธ
์์ฃผ ์ฌ์ฉํ๋ ํจํด๋ค์ ์ ๋ฆฌํด๋ดค์ด. ๋ถ๋งํฌํด๋๊ณ ํ์ํ ๋๋ง๋ค ์ฐธ๊ณ ํด! ๐
๐ค ๊ธฐ๋ณธ ๋ฌธ์ ํด๋์ค
| ํจํด | ์๋ฏธ | ์์ |
|---|---|---|
. |
์ค๋ฐ๊ฟ ์ ์ธ ๋ชจ๋ ๋ฌธ์ | a.c โ "abc", "a1c" |
\d |
์ซ์ [0-9] | \d{3} โ "123" |
\D |
์ซ์๊ฐ ์๋ ๋ฌธ์ | \D+ โ "abc" |
\w |
๋จ์ด ๋ฌธ์ [a-zA-Z0-9_] | \w+ โ "hello_123" |
\W |
๋จ์ด ๋ฌธ์๊ฐ ์๋ ๊ฒ | \W โ "@", "!" |
\s |
๊ณต๋ฐฑ ๋ฌธ์ | \s+ โ " ", "\t" |
\S |
๊ณต๋ฐฑ์ด ์๋ ๋ฌธ์ | \S+ โ "hello" |
๐ข ์๋์
| ํจํด | ์๋ฏธ | ์์ |
|---|---|---|
* |
0๋ฒ ์ด์ | ab*c โ "ac", "abc", "abbc" |
+ |
1๋ฒ ์ด์ | ab+c โ "abc", "abbc" |
? |
0๋ฒ ๋๋ 1๋ฒ | ab?c โ "ac", "abc" |
{n} |
์ ํํ n๋ฒ | \d{3} โ "123" |
{n,} |
n๋ฒ ์ด์ | \d{2,} โ "12", "123" |
{n,m} |
n๋ฒ ์ด์ m๋ฒ ์ดํ | \d{2,4} โ "12", "123", "1234" |
๐ฏ ์ต์ปค์ ๊ฒฝ๊ณ
| ํจํด | ์๋ฏธ | ์์ |
|---|---|---|
^ |
๋ฌธ์์ด ์์ | ^hello โ "hello world" |
$ |
๋ฌธ์์ด ๋ | world$ โ "hello world" |
\b |
๋จ์ด ๊ฒฝ๊ณ | \bcat\b โ "the cat" |
\B |
๋จ์ด ๊ฒฝ๊ณ ์๋ | \Bcat\B โ "concatenate" |
๐ฆ ์์ฃผ ์ฌ์ฉํ๋ ํจํด ๋ชจ์
์ด๋ฉ์ผ: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
URL: ^https?:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(\/.*)?$
์ ํ๋ฒํธ (ํ๊ตญ): ^01[0-9]-\d{3,4}-\d{4}$
๋ ์ง (YYYY-MM-DD): ^\d{4}-\d{2}-\d{2}$
์๊ฐ (HH:MM:SS): ^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$
IPv4 ์ฃผ์: ^(\d{1,3}\.){3}\d{1,3}$
16์ง์ ์์ ์ฝ๋: ^#[0-9A-Fa-f]{6}$
๋น๋ฐ๋ฒํธ (8์ ์ด์, ๋์๋ฌธ์+์ซ์): ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$
๐ ํ์ต ๋ฆฌ์์ค์ ๋ค์ ๋จ๊ณ
์ฌ๊ธฐ๊น์ง ์ ๋ง ๋ง์ ๋ด์ฉ์ ๋ฐฐ์ ์ด! ์ด์ ์ ๊ทํํ์๊ณผ std::regex๋ฅผ ์์ ์์ฌ๋ก ๋ค๋ฃฐ ์ ์์ ๊ฑฐ์ผ. ํ์ง๋ง ํ์ต์ ์ฌ๊ธฐ์ ๋์ด ์๋์ง! ๐
๐ ์ถ์ฒ ํ์ต ์๋ฃ
1. ์จ๋ผ์ธ ์ ๊ทํํ์ ํ ์คํฐ
โข regex101.com - ์ค์๊ฐ ํ ์คํธ์ ์ค๋ช ์ ๊ณต
โข regexr.com - ์๊ฐ์ ์ธ ์ธํฐํ์ด์ค
โข debuggex.com - ์ ๊ทํํ์ ์๊ฐํ
2. C++ ๊ณต์ ๋ฌธ์
โข cppreference.com/w/cpp/regex - ์๋ฒฝํ ๋ ํผ๋ฐ์ค
โข C++ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฌธ์
3. ์ค์ ์ฐ์ต
โข LeetCode, HackerRank์ ์ ๊ทํํ์ ๋ฌธ์
โข ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด๊ธฐ
โข ์ฌ๋ฅ๋ท์์ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ์ง์ ๊ณต์ ํ๊ธฐ
๐ ๋ค์ ๋จ๊ณ๋ก
์ด๊ธ โ ์ค๊ธ์ผ๋ก
โ ๊ธฐ๋ณธ ํจํด ์์ฑ ์๋ฃ
โ std::regex ํจ์๋ค ์ดํด
๐ฏ ๋ค์ ๋ชฉํ: ๋ณต์กํ ํจํด ์ต์ ํ, ์ฑ๋ฅ ํ๋
์ค๊ธ โ ๊ณ ๊ธ์ผ๋ก
โ ๋ณต์กํ ํจํด ์์ฑ ๊ฐ๋ฅ
โ ์ฑ๋ฅ ์ต์ ํ ์ดํด
๐ฏ ๋ค์ ๋ชฉํ: ์ปค์คํ ํ์ ๊ตฌํ, ๋ณด์ ๊ณ ๋ ค์ฌํญ ๋ง์คํฐ
๐ผ ์ค๋ฌด ์ ์ฉ ์์ด๋์ด
1. ๋ก๊ทธ ๋ถ์ ์์คํ
์๋ฒ ๋ก๊ทธ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ถ์ํ๊ณ ์ด์ ํจํด์ ๊ฐ์งํ๋ ์์คํ
2. ๋ฐ์ดํฐ ๊ฒ์ฆ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๋ค์ํ ํ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฆํ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
3. ํ ์คํธ ์ฒ๋ฆฌ ๋๊ตฌ
๋งํฌ๋ค์ด ํ์, ์ฝ๋ ํ์ด๋ผ์ดํฐ, ํ ํ๋ฆฟ ์์ง ๋ฑ
4. ๋ณด์ ๋๊ตฌ
๋ฏผ๊ฐ์ ๋ณด ํ์ง ๋ฐ ๋ง์คํน, SQL ์ธ์ ์ ๋ฐฉ์ด ๋ฑ
5. ์น ์คํฌ๋ํ
์น ํ์ด์ง์์ ํ์ํ ์ ๋ณด๋ฅผ ์ถ์ถํ๋ ํฌ๋กค๋ฌ
๐ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์! ์ฌ๊ธฐ๊น์ง ์ ๋ง ๊ธด ์ฌ์ ์ด์์ด. C++์ ์ ๊ทํํ์๊ณผ std::regex์ ๋ํด ๊ธฐ์ด๋ถํฐ ๊ณ ๊ธ ํ์ฉ๊น์ง ๋ชจ๋ ๋ค๋ค๋ดค์ง. ๐
์ ๊ทํํ์์ ์ฒ์์ ์ด๋ ต๊ฒ ๋๊ปด์ง ์ ์์ง๋ง, ํ ๋ฒ ์ต์ํด์ง๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋ผ. ํ ์คํธ ์ฒ๋ฆฌ๊ฐ ํ์ํ ๊ฑฐ์ ๋ชจ๋ ๊ณณ์์ ํ์ฉํ ์ ์๊ฑฐ๋ ! ๐ช
๐ ํต์ฌ ์์ฝ
1๏ธโฃ std::regex๋ C++11๋ถํฐ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํจ๋ ๊ฐ๋ ฅํ ์ ๊ทํํ์ ์์ง
2๏ธโฃ regex_match, regex_search, regex_replace ๋ฑ ๋ค์ํ ํจ์ ์ ๊ณต
3๏ธโฃ ํจํด ๋ฌธ๋ฒ์ ์ดํดํ๋ฉด ๋ณต์กํ ํ ์คํธ ์ฒ๋ฆฌ๋ ๊ฐ๋จํ๊ฒ ํด๊ฒฐ
4๏ธโฃ ์ฑ๋ฅ๊ณผ ๋ณด์์ ํญ์ ๊ณ ๋ คํด์ผ ํจ (ReDoS ๊ณต๊ฒฉ ์ฃผ์!)
5๏ธโฃ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ฉด์ ์ค๋ ฅ์ ํค์ฐ๋ ๊ฒ ์ต๊ณ ์ ํ์ต๋ฒ
์ด์ ์ฌ๋ฌ๋ถ๋ ํ ์คํธ ์ฒ๋ฆฌ์ ๋ง๋ฒ์ฌ๊ฐ ๋ ์ค๋น๊ฐ ๋์ด! ๐งโโ๏ธ ์ฌ๋ฅ๋ท์์ ๋ฐฐ์ด ๋ด์ฉ์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด๊ณ , ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ๋ ์ง์์ ๋๋ ๋ณด์. ํจ๊ป ์ฑ์ฅํ๋ ๊ฒ ๊ฐ์ฅ ๋น ๋ฅธ ๊ธธ์ด๋๊น! ๐
๊ถ๊ธํ ์ ์ด ์๊ฑฐ๋ ๋ ๋ฐฐ์ฐ๊ณ ์ถ์ ๋ด์ฉ์ด ์๋ค๋ฉด, ์ฌ๋ฅ๋ท์ ์ง์์ธ์ ์ฒ์์ ๋ค๋ฅธ ๊ธ๋ค๋ ์ฐพ์๋ณด๊ณ , ์ง์ ์ง๋ฌธ๋ ํด๋ด. ํ๋ก๊ทธ๋๋ฐ์ ํผ์๊ฐ ์๋๋ผ ํจ๊ป ๋ฐฐ์๊ฐ๋ ๊ฑฐ๋๊น! ๐ณ
๊ทธ๋ผ ์ฌ๋ฌ๋ถ์ ์ฝ๋ฉ ์ฌ์ ์ ํ์ด์ ๋น์ด! Happy Coding! ๐โจ
๐ฏ
์ ๊ทํํ์ ๋ง์คํฐ ์๋ฃ!
์ด์ ์ฌ๋ฌ๋ถ์ ํ ์คํธ ์ฒ๋ฆฌ์ ์ ๋ฌธ๊ฐ์ ๋๋ค
์ฌ๋ฅ๋ท์์ ๋ ๋ง์ ์ง์์ ํํํด๋ณด์ธ์! ๐
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.