diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c10a506 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +### Perl template +!Build/ +.last_cover_stats +/META.yml +/META.json +/MYMETA.* +*.o +*.pm.tdy +*.bs + +# Devel::Cover +cover_db/ + +# Devel::NYTProf +nytprof.out + +# Dist::Zilla +/.build/ + +# Module::Build +_build/ +Build +Build.bat + +# Module::Install +inc/ + +# ExtUtils::MakeMaker +/blib/ +/_eumm/ +/*.gz +/Makefile +/Makefile.old +/MANIFEST.bak +/pm_to_blib +/*.zip + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..23baf58 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# 디폴트 무시된 파일 +/shelf/ +/workspace.xml diff --git a/.idea/copyright/Elex_Project.xml b/.idea/copyright/Elex_Project.xml new file mode 100644 index 0000000..72d9189 --- /dev/null +++ b/.idea/copyright/Elex_Project.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..ce14878 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Writerside/c.list b/Writerside/c.list new file mode 100644 index 0000000..c4c77a2 --- /dev/null +++ b/Writerside/c.list @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/Writerside/cfg/buildprofiles.xml b/Writerside/cfg/buildprofiles.xml new file mode 100644 index 0000000..5022d1e --- /dev/null +++ b/Writerside/cfg/buildprofiles.xml @@ -0,0 +1,17 @@ + + + + + + + + + true + + + + diff --git a/Writerside/images/completion_procedure.png b/Writerside/images/completion_procedure.png new file mode 100644 index 0000000..3535a3f Binary files /dev/null and b/Writerside/images/completion_procedure.png differ diff --git a/Writerside/images/completion_procedure_dark.png b/Writerside/images/completion_procedure_dark.png new file mode 100644 index 0000000..a65beb0 Binary files /dev/null and b/Writerside/images/completion_procedure_dark.png differ diff --git a/Writerside/images/convert_table_to_xml.png b/Writerside/images/convert_table_to_xml.png new file mode 100644 index 0000000..2518a64 Binary files /dev/null and b/Writerside/images/convert_table_to_xml.png differ diff --git a/Writerside/images/convert_table_to_xml_dark.png b/Writerside/images/convert_table_to_xml_dark.png new file mode 100644 index 0000000..4716122 Binary files /dev/null and b/Writerside/images/convert_table_to_xml_dark.png differ diff --git a/Writerside/images/new_topic_options.png b/Writerside/images/new_topic_options.png new file mode 100644 index 0000000..bc6abb6 Binary files /dev/null and b/Writerside/images/new_topic_options.png differ diff --git a/Writerside/images/new_topic_options_dark.png b/Writerside/images/new_topic_options_dark.png new file mode 100644 index 0000000..bf3e48d Binary files /dev/null and b/Writerside/images/new_topic_options_dark.png differ diff --git a/Writerside/p.tree b/Writerside/p.tree new file mode 100644 index 0000000..70e4c7c --- /dev/null +++ b/Writerside/p.tree @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Writerside/topics/Array.md b/Writerside/topics/Array.md new file mode 100644 index 0000000..0142abf --- /dev/null +++ b/Writerside/topics/Array.md @@ -0,0 +1,217 @@ +# 배열 + +## 배열의 생성 + +괄호 안에 배열의 요소를 나열해서 배열을 생성합니다. + +```perl +@array = ('Charlie', 'Steve', 34); +``` + +또는, **qw//** 연산자를 사용해서 배열을 만들 수도 있습니다. qw 연산자는 공백 문자나 줄바꿈을 기준으로 구분된 문자열의 배열을 생성합니다. + +```perl +@array = qw/Charlie Steve 37/; +``` + +### 연속된 범위의 배열 (Range) + +일련의 숫자나 문자의 배열은 다음과 같이 생성할 수 있습니다. + +```perl +@range = (0..10); +print "@range\n"; # 0 1 2 3 4 5 6 7 8 9 10 + +@range = (a..f); +print "@range\n"; # a b c d e f +``` + +## 배열의 요소에 접근 + +0부터 시작되는 인덱스를 사용해서 배열의 각 항목에 접근할 수 있습니다. 특이하게, 인덱스에 음수를 사용할 수도 있습니다. 배열의 요소는 스칼라 타입이기 때문에 배열의 요소를 참조할 때에는 변수명 앞에 `$`가 붙습니다. + +```perl +@array = qw/일 월 화 수 목 금 토/; +print "$array[0]\n"; # 일 +print "$array[6]\n"; # 토 +print "$array[-1]\n"; # 토 +``` + +## 배열의 크기 + +배열을 스칼라 변수에 할당하면 배열의 크기가 할당됩니다. 이 때, 배열의 크기는 유효한 요소의 갯수가 아니라, 배열의 물리적인 크기입니다. 또는, `$size = scalar @array;`처럼 사용할 수도 있습니다. `$#array`는 배열의 마지막 인덱스를 나타냅니다. + +```perl +@array = (1,2,3); +$array[10] = 10; + +# 배열을 스칼라 변수에 할당하면 배열의 크기가 할당됩니다. +$size = @array; # 또는, $size = scalar @array; +# 배열의 마지막 인덱스 +$max_index = $#array; + +print "Size: $size\n"; # 11 +print "Max index: $max_index\n"; # 10 +``` + +## 배열 요소의 삽입과 제거 + +- push + + 배열의 맨 뒤에 새로운 요소를 추가합니다. + +- pop + + 배열에서 맨 마지막 요소를 꺼냅니다. 꺼낸 요소는 배열에서 삭제됩니다. + +- shift + + 배열에서 첫 번쨰 요소를 꺼냅니다. 꺼낸 요소는 배열에서 삭제됩니다. + +- unshift + + 배열의 맨 앞에 새로운 요소를 추가합니다. 새로운 배열의 크기를 반환합니다. + + +```perl +@array = (1, 2, 3); + +push (@array, 4); # 괄호는 없어도 됩니다. +# (1,2,3,4) +push (@array, (5, 6, 7)); +# (1,2,3,4,5,6,7) +print "Array: ".scalar @array.": (".join(', ', @array).")\n"; +``` + +```perl +$val = pop @array; # $val == 7 +# (1,2,3,4,5,6) +``` + +```perl +$val = shift @array; # $val == 1 +# (2,3,4,5,6) +``` + +```perl +$new_size = unshift @array, (0,1); # $new_size == 7 +# (0,1,2,3,4,5,6) +``` + +## 배열의 결합 + +배열 안에 배열을 넣으면 하나의 평평한 배열로 합쳐집니다. + +```perl +@array = (1,2,(3,4,5)); +# (1,2,3,4,5) +``` + +## 부분 배열 + +```perl +@days = qw/일 월 화 수 목 금 토/; +@weekdays = @days[1,2,3,4,5]; # (월,화,수,목,금) +# 또는, 범위 연산자를 사용해서 +@weekdays = @days[1..5]; # (월,화,수,목,금) +``` + +### Splice + +- splice(@array, offset, length) + + 어떤 배열에서 주어진 인덱스부터 길이만큼을 제거합니다. 제거된 부분 배열을 반환합니다. + +- splice(@array, offset, length, new_items) + + 어떤 배열에서 주어진 인덱스부터 길이만큼을 제거하고, 새로운 데이터로 채웁니다. 제거된 부분 배열을 반환합니다. + + +```perl +@days = qw/일 월 화 수 목 금 토/; +@weekdays = splice (@days, 1, 5); # array, offset, length +# @days == (일,토) +# @weekdays == (월,화,수,목,금) +``` + +```perl +@days = qw/일 월 화 수 목 금 토/; +@weekdays = splice (@days, 1, 5, (1..3)); # array, offset, length, new_items +# @days == (일,1,2,3,토) +# @weekdays == (월,화,수,목,금) +``` + +## 배열 <=> 문자열 + +### split + +문자열을 배열로 쪼갤 때는 split을 사용합니다. + +- split(SEPARATOR, EXPRESSION, LIMIT) + - LIMIT은 반환되는 배열의 최대 길이를 제한할 때 사용됩니다. + +```perl +@array = split(',', 'Charlie,Steve,Jane'); +# (Charlie, Steve, Jane) +@array = split('-', 'Charlie-Steve-Jane', 2); +# (Charlie, Steve-Jane) +``` + +### join + +배열의 각 항목을 문자열로 합칠 때는 join을 사용합니다. + +- join(SEPARATOR, LIST) + +```perl +$str = join(', ', @array); +``` + +## 정렬 + +### sort + +sort는 배열을 정렬할 때 사용합니다. 정렬된 새로운 배열을 반환합니다. 문자열을 정렬할 때에는 ASCII 코드 순으로 정렬되므로 대소문자에 주의해야 하며, 숫자인 경우에도 별도의 서브루틴이 필요합니다. + +- sort LIST + +- sort SUBROUTINE LIST + + 별도의 서브루틴을 명시해서 정렬 방법을 지정할 수 있습니다. + + +```perl +@array = qw/Chicken Pizza Steak Noodle Cola Cider/; +print "Before sort: @array\n"; + +@array = sort @array; +print "After sort: @array\n"; # Chicken Cider Cola Noodle Pizza Steak +``` + +```perl +my @array = (1,5,30,7,3,62,9,3); +@array = sort {$a <=> $b} @array; # 우주선 연산자는 숫자의 비교에 사용됩니다. +# $a, $b는 sort() 함수에서 정의한 글로벌 변수입니다. +``` + +## 존재 여부 + +- exists ITEM + + 배열의 어떤 요소가 유효한지를 확인하려면 exists를 사용합니다. + + ```perl + @array = (1..3); + if(exists($array[7])){ + print "exists.\n"; + } else { + print "not exists.\n"; + } + ``` + + +## 특수 변수 + +### $[ + +PERL의 배열은 0부터 시작됩니다. 하지만 만일, `$[ = 1;`이라고 해두면 모든 배열의 첫 번째 인덱스는 1이 됩니다. \ No newline at end of file diff --git a/Writerside/topics/Base64.md b/Writerside/topics/Base64.md new file mode 100644 index 0000000..be19e88 --- /dev/null +++ b/Writerside/topics/Base64.md @@ -0,0 +1,8 @@ +# Base64 + +```perl +use MIME::Base64; + +$encoded = encode_base64('some text'); +$decoded = decode_base64($encoded); +``` \ No newline at end of file diff --git a/Writerside/topics/CGI.md b/Writerside/topics/CGI.md new file mode 100644 index 0000000..50170ee --- /dev/null +++ b/Writerside/topics/CGI.md @@ -0,0 +1,162 @@ +# Common Gateway Interface + +## CGI 환경 변수 + +- CONTENT_TYPE + +- CONTENT_LENGTH + +- DOCUMENT_ROOT + +- HTTP_ACCEPT + +- HTTP_COOKIE + +- HTTP_REFERER + +- HTTP_USER_AGENT + +- PATH_INFO + +- QUERY_STRING + +- REMOTE_ADDR + +- REMOTE_HOST + +- REQUEST_METHOD + +- SCRIPT_FILENAME + +- SCRIPT_NAME + +- SERVER_NAME + +- SERVER_PORT + +- SERVER_SOFTWARE + + +```perl +my $buffer; +$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; +if ($ENV{'REQUEST_METHOD'} eq "GET") { + $buffer = $ENV{'QUERY_STRING'}; + +} elsif ($ENV{'REQUEST_METHOD'} eq "POST") { + read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); + +} + +print "$ENV{SERVER_PROTOCOL} 200 OK\r\n"; +print "Content-type:text/plain\r\n"; +print "\r\n"; +print "Hello\n"; +``` + +## CGI + +```bash +sudo cpanm CGI +``` + +```perl +#!/usr/bin/perl +use warnings; +use strict; + +use CGI; + +my $query = CGI->new; + +$bday = $query->param("birthday"); +print $query->header(); +print $query->p("Your birthday is $bday."); +``` + +- keywords + +- http + +- param + +- append + +- import_names + +- delete + +- delete_all + +- save + +- url + +- header + +- redirect + +- cookie + +- dump + + +```perl +use CGI qw/ :cgi -utf8 /; + +$CGI::DISABLE_UPLOADS = 1; +$CGI::POST_MAX = 102_400; # 100 KB + +print $cgi->header('text/html','204 No response'); + +my @keywords = $query->keywords; +my @names = $query->param; +my $value = $query->param('name'); + +print $query->redirect('https://example.com'); +print $query->redirect( + -uri => 'https://example.com', + -status => '301 Moved Permanently' +); +``` + +POST로 전송된 데이터를 직접 처리해야 하는 경우에는 다음과 같이 데이터를 가져올 수 있습니다. + +```perl +my $data = $query->param('POSTDATA'); +my $data = $query->param('PUTDATA'); +``` + +업로드된 파일은 다음과 같이 처리합니다. + +```perl +my $file_handle = $query->upload('uploaded_file'); +``` + +## NGINX와 함께 CGI 사용하기 + +[FCGI Wrap | NGINX](https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/) + +```bash +sudo apt install fcgiwrap spawn-fcgi +cp /usr/share/doc/fcgiwrap/examples/nginx.conf /etc/nginx/fcgiwrap.conf +``` + +설정 파일에서 필요한 부분은 수정합니다. + +```nginx +server { + listen 80; + index index.html; + root /var/www; + ignore_invalid_headers on; + include /etc/nginx/fcgiwrap.conf; + location /cgi-bin { + gzip off; + fastcgi_param SERVER_NAME $http_host; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include /etc/nginx/fastcgi_params; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + } +} +``` \ No newline at end of file diff --git a/Writerside/topics/Condition.md b/Writerside/topics/Condition.md new file mode 100644 index 0000000..a1b05f4 --- /dev/null +++ b/Writerside/topics/Condition.md @@ -0,0 +1,126 @@ +# 조건문 + +PERL에는 boolean 형식의 데이터가 없으며, 숫자 0, 문자열 '0', 빈 문자열, 빈 리스트, 값이 할당되지 않은(undefined) 변수의 경우에는 거짓으로, 그 외의 경우에는 참으로 판단됩니다. + +## if + +실행문 뒤에 if를 쓸 수도 있습니다. + +```perl +$a = 1; +print "Hello\n" if ($a == 1); +``` + +## if … elsif … else … + +실행문이 한 줄인 경우라도 중괄호가 반드시 필요합니다. + +```perl +if ($condition){ + print "true\n"; +} else { + print "false\n"; +} +``` + +## unless + +```perl +$a = 1; +print "Hello\n" unless ($a == 1); +``` + +## unless … elsif … else … + +unless는 조건식이 거짓일 때 처리됩니다. + +```perl +$var = -10; + +unless ($var){ + print "false\n"; +} elsif ($var>=0) { + print "positive\n"; +} else { + print "negative\n"; +} +# negative +``` + +## 조건 연산자 + +```perl +$var = 10; +$value = ($var>=0) ? "Positive" : "Negative"; +print "$value\n"; +``` + +## given … when … default … + +```perl +use v5.10; # given문을 사용하려면 이렇게 선언해야 합니다. +no warnings 'experimental'; + +$var = 2; +given ($var){ + when (1) { + print "one\n"; + } + when (2) { + print "two\n"; + } + default { + print "many\n"; + } +} +``` + +```perl +use v5.12; + +my $var = 2; +my $value; +given ($var){ + $value = 'One' when (1); + $value = 'Two' when (2); + default { + $value = 'Many'; + } +} +print "$value\n"; +``` + +```perl +use v5.12; + +my $var = 'a'; +my $value; +given ($var){ + $value = 'Number' when /\d/; # when절에 정규표현식을 사용할 수도 있습니다. + $value = 'Character' when /[a-zA-Z]/; + default { + $value = 'Unknown'; + } +} +print "$value\n"; +``` + +## switch .. case .. else .. + +switch 구문은 Switch 모듈의 일부이므로 이를 사용하려면 `use Switch;`를 선언해야합니다. + +```perl +use Switch; + +switch($var) { + case 1 { + print "One"; + } + case "a" { + print "string a"; + } + else { + print "something else."; + } +} +``` \ No newline at end of file diff --git a/Writerside/topics/Data-type.md b/Writerside/topics/Data-type.md new file mode 100644 index 0000000..7d2d399 --- /dev/null +++ b/Writerside/topics/Data-type.md @@ -0,0 +1,219 @@ +# 자료형 + +| 타입 | 기호 | +| --- | --- | +| 스칼라 | \$ | +| 배열 | @ | +| 해시 | % | + +## 스칼라 (Scalar) + +스칼라는 숫자나 문자열 같은 단순한 변수형입니다. 스칼라 타입의 변수는 `$`로 시작합니다. 변수의 주소를 담는 참조의 경우에도 스칼라 타입입니다. + +### 숫자 + +```perl +$num1 = -100; +$num2 = 108.32; +$num3 = 0xff; +$num4 = 3.14E7; +$num5 = 123_456_789; # 큰 숫자의 경우 3자리마다 '_'를 넣어서 읽기 쉽게 할 수 있습니다. +``` + +#### 수학 함수 + +- abs +- atan2 +- cos +- exp +- hex +- int +- log +- oct +- rand +- sin +- sqrt +- srand + +### 문자열 + +문자열은 홑따옴표('') 또는 쌍따옴표("")로 묶습니다. 쌍 따옴표로 묶인 문자열의 경우에는 문자열 내에 포함된 변수를 보간 처리(interpolation)하지만, 홑 따옴표의 경우에는 처리하지 않습니다. + +```perl +$name = 'charlie'; +$age = 14; +$str1 = "\u$name is $age-year-old.\n"; +$str2 = '\u$name is $age-year-old.\n'; + +print $str1; # Charlie is 14-year-old. +print $str2; # \u$name is $age-year-old.\n +``` + +`q//`는 홑 따옴표처럼, 그리고 `qq//`는 쌍 따옴표처럼 작동합니다. 문자열에 따옴표가 포함된 경우에 유용합니다. `//` 대신 `()`등을 사용할 수있습니다. + +```perl +$str = qq/"How are you?"/; +``` + +#### 이스케잎 문자열 (Escape sequence) + +| 이스케잎 문자 | | +| --- | --- | +| `\\` | 역슬래시 | +| `\'`, `\"` | 따옴표 | +| `\n`, `\r`, `\t` | 줄바꿈과 탭 | +| `\xnn` | 16진수 형식의 숫자 | +| `\u` | 다음 문자를 대문자로 만듭니다. | +| `\l` | 다음 문자를 소문자로 만듭니다. | +| `\U`, `\L` | 이어지는 모든 문자를 대문자/소문자로 만듭니다. | +| `\Q` | 이어지는 모든 문자 중 영문자/숫자가 아닌 문자를 역슬래시 처리합니다. | +| `\E` | `\U`, `\L`, `\Q`를 끝냅니다. | + +#### 히어독 (Here doc) + +히어독은 문자열의 길이가 긴 경우에 유용하게 사용됩니다. 히어독은 `<<식별자`로 시작하고 `식별자`로 끝납니다. + +```perl +$name = 'Charlie'; +$age = 14; + +$var = <available_drivers; + +foreach(@driver_names){ + print "$_\n"; +} +``` + +## 데이터베이스 연결 + +```perl +# SQLite +my $dsn = "DBI:SQLite:dbname=$dbFile"; +my $dbh = DBI->connect($dsn, $dbUsername, $dbPassword); +``` + +https://metacpan.org/pod/DBD::SQLite + +```perl +# MariaDB +my $dsn = "DBI:MariaDB:database=$database;host=$hostname;port=$port"; +my $dbh = DBI->connect($dsn, $dbUsername, $dbPassword); +``` + +https://metacpan.org/pod/DBD::MariaDB + +`connect`에 4번째 매개 변수로 자동 커밋 등의 옵션을 지정할 수 있습니다. + +```perl +my $dbh = DBI->connect('DBI:SQLite:dbname=$dbFile', undef, undef, { + AutoCommit => 1, # 자동 커밋을 사용하도록 지정합니다. + RaiseError => 1 # 오류 처리를 자동으로 하도록 지정합니다. +}); +``` + +## 그래서, 샘플 + +```perl +#!/usr/bin/perl +use warnings; +use strict; +use DBI; + +my $dbFile = 'test.db'; +my $dbUsername = ''; +my $dbPassword = ''; + +# 데이터베이스에 연결 +my $dbh = DBI->connect("DBI:SQLite:dbname=$dbFile", $dbUsername, $dbPassword); + + +my $table = 'test'; +# 간단한 SQL 실행에는 do를 사용합니다. - 테이블 생성 +my $sth = $dbh->do("CREATE TABLE IF NOT EXISTS $table (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);"); + +# 삽입 +$sth = $dbh->prepare("INSERT INTO $table (name, age) VALUES (?,?);"); +$sth->execute('Charlie', 13); +$sth->execute('Steve', 34); +$sth->execute('Mary', 34); +$dbh->commit() or die $DBI::errstr; + +# 조회 +$sth = $dbh->prepare("SELECT * FROM $table WHERE age=?;"); +$sth->execute(34); +while(my @row = $sth->fetchrow_array()){ + my ($id, $name, $age) = @row; + print "$id | $name | $age\n"; +} + +# 연결 끊기 +my $rc = $dbh->disconnect or warn $dbh->errstr; +``` + +### 조회 결과를 바인딩 + +`fetch`를 `bind_columns`와 함께 사용하면 빠르게 결과값을 처리할 수 있습니다. + +```perl +$sth = $dbh->prepare("SELECT * FROM $table WHERE name=?;"); +$sth->execute('Charlie'); +my ($id, $name, $age); +$sth->bind_columns(\$id, \$name, \$age); +while($sth->fetch()){ + print "$id | $name | $age\n"; +} +``` + +`fetchrow_hashref`는 해시에 대한 참조를 반환합니다. `fetch`보다는 다소 느립니다. + +```perl +$sth = $dbh->prepare("SELECT * FROM $table WHERE name=?;"); +$sth->execute('Steve'); +while(my $row = $sth->fetchrow_hashref()){ + print "$row->{id} | $row->{name} | $row->{age}\n"; +} +``` + +## 메서드 + +### 데이터베이스 핸들 + +- `do` + +- `prepare` SQL 구문 핸들을 반환합니다. + +- `commit` + +- `last_insert_id` + +- `begin_work` 자동 커밋을 중단하고 트랜잭션을 시작합니다. + +- `rollback` 커밋되지 않은 동작을 되돌립니다. + +- `disconnect` + + +### 스테이트먼트 핸들 + +- `execute` SQL을 실행합니다. + +- `last_insert_id` + +- `fetchrow_array` 조회 결과의 다음 행을 배열로 반환합니다. + +- `fetch` = `fetchrow_arrayref` 조회 결과의 다음 행을 배열 참조로 반환합니다. + +- `fetchrow_hashref` + +- `bind_columns` + +- `rows` + +- `finish` + +- `dump_results` \ No newline at end of file diff --git a/Writerside/topics/Date-and-Time.md b/Writerside/topics/Date-and-Time.md new file mode 100644 index 0000000..a2e2071 --- /dev/null +++ b/Writerside/topics/Date-and-Time.md @@ -0,0 +1,68 @@ +# 날짜와 시간 + +## time + +1970-01-01 이후부터의 경과 시간을 초 단위로 반환합니다. + +```perl +$epoch = time(); +``` + +## localtime + +매개 변수로 시간을 전달할 수 있으며, 생략되면 현재 시간이 사용됩니다. localtime()을 스칼라로 받으면 시간을 나타내는 문자열 표현이되고, 배열로 받으면 9개의 요소를 가진 배열이 됩니다. + +```perl +my $now = localtime(); +print "$now\n"; # Thu Feb 11 15:19:03 2021 +``` + +```perl +$epoch = time(); +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($epoch); +``` + +- sec : 초. 0~59 +- min : 분. 0 ~ 59 +- hour : 시. 0 ~ 24 +- mday : 일. 1 ~ 31 +- mon : 월. 0 ~ 11 +- year : 년. 1900년부터. +- wday : 요일. 일요일부터. +- yday : 1월 1일 이후의 날짜 수. +- isdst : 일광절약제 적용 여부. + +```perl +print &date_format."\n"; +sub date_format{ + my @weeks = qw(일 월 화 수 목 금 토); + my $time = (defined $_[0]) ? $_[0] : time(); + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + $mon += 1; + $year += 1900; + $wday = $weeks[$wday]; + return "$year년 $mon월 $mday일 $wday요일 $hour시 $min분 $sec초"; +} +``` + +```perl +print &ymdhms."\n"; + +sub ymdhms{ + my $time = (defined $_[0]) ? $_[0] : time(); + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + $mon += 1; + $year += 1900; + sprintf ("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec); +} +``` + +## gmtime + +UTC 시간입니다. localtime()과 같은 방식으로 사용하면 됩니다. 다만, UTC시간이므로, $isdst는 항상 0입니다. + +```perl +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time); +``` + +# \ No newline at end of file diff --git a/Writerside/topics/Error-Handling.md b/Writerside/topics/Error-Handling.md new file mode 100644 index 0000000..0ae9d23 --- /dev/null +++ b/Writerside/topics/Error-Handling.md @@ -0,0 +1,28 @@ +# 오류 처리 + +- die + + 메시지를 출력하고 프로세스가 종료됩니다. + +- warn + + die와 마찬가지로 메시지를 출력하지만, 종료되지는 않습니다. + + +특수 변수인 `$!`에는 실제 오류 메시지가 들어있습니다. + +```perl +if (...){ + +} else { + die "Error: xxx - $!"; +} +``` + +```perl +open(...) or die "Error: xxx - $!"; +``` + +```perl +warn "xxxx" unless (...); +``` \ No newline at end of file diff --git a/Writerside/topics/File-system.md b/Writerside/topics/File-system.md new file mode 100644 index 0000000..167d834 --- /dev/null +++ b/Writerside/topics/File-system.md @@ -0,0 +1,100 @@ +# 파일과 디렉토리 + +## 파일 확인 + +```perl +$filename = '/home/elex/test.txt'; +if (-e $filename){ + ... +} +``` + +| 파일 테스트 연산자 | 내용 | +| --- | --- | +| -e | 파일이 존재하는지 여부 | +| -r, -R | 파일을 읽을 수 있는지 여부 | +| -w, -W | 파일에 쓸 수 있는지 여부 | +| -x, -X | 파일을 실행할 수 있느지 여부 | +| -o, -O | 파일에 대한 소유권이 있느지 여부 | +| -z | 빈 파일인지 여부 | +| -s | 파일의 크기를 반환 | +| -f | 일반 파일인지 여부 | +| -d | 디렉토리인지 여부 | +| -l | 심볼릭 링크인지 여부 | +| -p | 파이프인지 여부 | +| -S | 소켓인지 여부 | +| -T | 아스키 텍스트 파일인지 여부 | +| -B | 이진 파일인지 여부 | + +```perl +my $filename = "file.txt"; + +if (-e -f -r $filename){ # 여러 개를 동시에 물어볼 수 있습니다. + print "OK\n"; +} else { + print "Not OK.\n"; +} +``` + +## 이름 변경 + +```perl +rename ('/home/elex/file.txt', '/home/elex/file2.txt'); +``` + +## 파일 삭제 + +```perl +unlink ('/home/elex/file.txt'); +``` + +## 파일 목록 조회 + +```perl +my @files = glob('/tmp/*.pl'); +``` + +## 디렉토리 생성 + +```perl +mkdir ('/tmp/test') or die "$!"; +``` + +### make_path + +디렉토리 구조를 한 번에 생성하려면 **File::Path** 모듈을 사용해야 합니다. + +```perl +#!/usr/bin/perl +use strict; +use File::Path qw(make_path remove_tree); + +make_path('hello/world', 'hello2'); +make_path('hello3', {mode => 0711, user => 'elex', group => 'users'}); +remove_tree('world'); +``` + +## 디렉토리 제거 + +```perl +rmdir ('/tmp/test') or die "$!"; +``` + +## 디렉토리 이동 + +```perl +chdir ('/tmp/test') or die "$!"; +``` + +## 링크 + +```perl +link($old_file, $new_file); +symlink($old_file, $new_file); +``` + +## 그리고, + +- chmod + +- chown \ No newline at end of file diff --git a/Writerside/topics/GUI.md b/Writerside/topics/GUI.md new file mode 100644 index 0000000..8359482 --- /dev/null +++ b/Writerside/topics/GUI.md @@ -0,0 +1,62 @@ +# GUI - Tk + +```bash +sudo apt install perl-tk +``` + +```perl +#!/usr/bin/perl +use strict; +use utf8; +use Tk; + +my $mw = MainWindow->new; +$mw->Label(-text => '안녕!')->pack; +$mw->Button( + -text => '종료', + -command => sub { exit }, +)->pack; +MainLoop; +``` + +https://metacpan.org/pod/distribution/Tk/pod/UserGuide.pod + +## Layouts + +### pack + +### grid + +### place + +## Widgets + +### Button + +### Checkbutton + +### Radiobutton + +### Label + +### Entry + +### Scrollbar + +### Listbox + +### Text + +### Canvas + +### Scale + +### Menubutton + +### Menu + +### Optionmenu + +### Frame + +### Toplevel \ No newline at end of file diff --git a/Writerside/topics/Hash.md b/Writerside/topics/Hash.md new file mode 100644 index 0000000..4f8b719 --- /dev/null +++ b/Writerside/topics/Hash.md @@ -0,0 +1,109 @@ +# 해시 + +해시는 키/값 쌍의 집합입니다. + +## 해시의 생성 + +```perl +# 각각의 키에 대응하는 값을 하나하나 할당하며 생성합니다. +$ages{'Charlie'} = 14; +$ages{'Steve'} = 37; +$ages{'Jane'} = 22; + +# 배열과 유사하게 키와 값을 번갈아 가며 정의합니다. +%ages = ('Charlie', 14, 'Steve', 37, 'Jane', 22); + +# 콤마로 구분하는 대신 =>를 사용하면 코드가 좀 더 명확해집니다. +%ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); + +# 키에 따옴표 없이 사용해도 되지만, 이 경우에는 키에 공백 문자가 없어야 합니다. +%ages = (Charlie=> 14, Steve=> 37, Jane=> 22); +``` + +## 해시 요소의 참조 + +해시 요소를 참조할 때에는 중괄호`{}`를 사용합니다. + +```perl +%ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); + +print "Charlie: $ages{'Charlie'}\n"; +print "Steve: $ages{'Steve'}\n"; +print "Jane: $ages{Jane}\n"; # 따옴표로 묶지 않아도 됩니다. +``` + +## 요소의 삽입과 제거 + +해시에 새로운 항목을 삽입하려면 단순히 할당문을 사용하면 됩니다. 해시에서 아이템을 제거하려면 delete를 사용합니다. + +```perl +# 해시에 새로운 아이템을 삽입합니다. +$ages{'Julie'} = 7; + +# 해시에서 아이템을 제거합니다. +delete $ages{'Steve'}; +``` + +## 키 배열 + +- keys HASH + + 해시의 키를 배열로 반환합니다. + +- values HASH + + 마찬가지로, 해시의 값을 배열로 반환합니다. + + +```perl +%ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); + +@keys = keys %ages; +@values = values %ages; + +print "@keys\n"; # Charlie Jane Steve +print "@values\n"; # 14 22 37 +``` + +## 해시의 크기 + +해시의 크기는 키 배열 또는 값 배열의 크기와 같으므로, 다음과 같은 방식으로 해시의 크기를 알 수 있습니다. + +```perl +%ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); + +@keys = keys %ages; +$size_of_hash = @keys; +``` + +## 존재 여부 + +- exists ITEM + + 해시의 어떤 요소가 유효한지를 확인하려면 exists를 사용합니다. + + ```perl + %ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); + if(exists($ages{'Julie'})){ + print "exists.\n"; + } else { + print "not exists.\n"; + } + ``` + + +## 부분 집합 + +```perl +%ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); + +%slice = %ages{'Charlie', 'Steve'}; +``` + +아래와 같이하면, 부분 해시의 값을 배열로 구할 수 있습니다. + +```perl +%ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); +@values = @ages{'Charlie', 'Steve'}; # @ages입니다, %가 아니라. +print "@values\n"; # 14 37 +``` \ No newline at end of file diff --git a/Writerside/topics/Hello-world.md b/Writerside/topics/Hello-world.md new file mode 100644 index 0000000..087e6fe --- /dev/null +++ b/Writerside/topics/Hello-world.md @@ -0,0 +1,34 @@ +# Hello, World + +```perl +#!/usr/bin/perl + +# This is a simple Hello World program. +print "Hello, World.\n"; +``` + +시스템에 설치된 Perl의 버전을 확인하려면 `perl -v`를 입력하세요. + +PERL 스크립트 파일은 확장자로 *.pl*을 사용합니다. + +`chmod`명령으로 파일에 실행 권한을 주는 것도 잊지 마세요. + +여느 스크립트 언어들과 마찬가지로 해시뱅(`#!`)으로 시작해서 인터프리터의 경로를 알려주며 시작됩니다. 인터프리터의 경로를 확인하려면 `which perl` 명령을 사용합니다. + +PERL의 주석은 `#`로 시작됩니다. + +`print`문을 사용해서 화면에 간단히 출력할 수 있습니다. + +## 문서화 주석 + +어떤 줄이 `=begin` 등으로 시작되면 문서화 주석(POD)이 시작됩니다. `=cut`으로 시작되는 줄을 만나면 주석이 끝납니다. + +```perl +#!/usr/bin/perl + +=begin +This is a sample Hello World program using Perl. +Author: Elex. +=cut +print "Hello, World.\n"; +``` \ No newline at end of file diff --git a/Writerside/topics/Http.md b/Writerside/topics/Http.md new file mode 100644 index 0000000..c3a32bc --- /dev/null +++ b/Writerside/topics/Http.md @@ -0,0 +1,131 @@ +# Http Client + +```perl +#!/usr/bin/perl +use warnings; +use strict; + +use URI::URL; +use HTTP::Headers; +use HTTP::Request; +use LWP::UserAgent; + +my $url = new URI::URL('https://www.example.com'); +my $headers = new HTTP::Headers( + 'Accept' => 'text/html', + 'User-Agent' => 'Elex/1.0' +); +my $request = new HTTP::Request('GET', $url, $headers); +my $user_agent = new LWP::UserAgent; + +my $response = $user_agent->request($request); +if ($response->is_success) { + print $response->content; +} else { + print $response->message; +} +``` + +## LWP::UserAgent + +```perl +my $user_agent = new LWP::UserAgent; +``` + +- request + +- credentials + +- get_basic_credentials + +- timeout + + +## HTTP::Request + +```perl +my $request = new HTTP::Request($method, $url, $headers, $content); +``` + +- method : GET, POST 등 + +- url : 문자열 또는 `URI::URL` 객체 + +- headers : `HTTP::Headers` 객체 + +- content : 요청 바디 + + +## HTTP::Response + +```perl +my $response = $user_agent->request($request); +``` + +서버 측에서 응답을 생성하려는 경우에는 + +```perl +my $response = HTTP::Response->new($status_code, $msg, $header, $content); +``` + +- code + +- message + +- is_success + + +## HTTP::Headers + +```perl +my $headers = new HTTP::Headers( + 'name' => 'value', ... +); +``` + +- push_header + +- remove_header + + +## HTTP::Status + +- is_info + +- is_success + +- is_redirect + +- is_client_error + +- is_server_error + +- is_error + + +## URI::URL + +```perl +my $url = new URI::URL($url); +``` + +- scheme + +- host + +- port + +- path + +- query + +- user + +- password + + +## URI::Escape + +- uri_escape + +- uri_unescape \ No newline at end of file diff --git a/Writerside/topics/IO.md b/Writerside/topics/IO.md new file mode 100644 index 0000000..61cb5ab --- /dev/null +++ b/Writerside/topics/IO.md @@ -0,0 +1,71 @@ +# I/O + +## 표준입력 + +```perl +my $line = ; +print "Input = $line\n"; +``` + +## 파일 I/O + +```perl +# 파일 핸들러를 쓰기 모드로 엽니다. +open(FILE, '>', "file.txt") or die $!; # 핸들러, 모드, 파일이름 + +# 파일에 문자열을 출력합니다. +print FILE "Hello"; + +# 파일 핸들러를 닫습니다. +close(FILE); +``` + +| 모드 | | +| --- | --- | +| <, r | 읽기 모드 | +| >, w | 쓰기 모드. 파일이 없으면 생성. 기존 데이터는 제거됨. | +| >>, a | 추가 모드. 파일이 없으면 생성. | +| +<, r+ | 읽기 및 쓰기 | +| +>, w+ | 읽기 및 쓰기. 파일이 없으면 생성. 기존 데이터는 제거됨. | +| +>>, a+ | 읽기 및 쓰기. 추가 모드. 파일이 없으면 생성. | + +### 파일 읽기 + +파일 핸들러로부터 한 줄을 읽으려면 다음과 같이 합니다. + +```perl +$line = ; +``` + +여러 줄을 한 번에 읽으려면 배열을 사용합니다. + +```perl +@lines = ; +``` + +대부분의 경우, 아래와 같이 반복문으로 처리합니다. + +```perl +open(FILE, '<', 'file.txt') or die $!; + +while (){ + $line = $_; +} + +close(FILE); +``` + +## 디렉토리 + +- opendir +- readdir +- closedir + +```perl +opendir(DIR, $dirname) || die "Error in opening dir $dirname"; + +while($filename = readdir(DIR)){ + print($filename,"\n"); +} +closedir(DIR); +``` \ No newline at end of file diff --git a/Writerside/topics/Json.md b/Writerside/topics/Json.md new file mode 100644 index 0000000..1acf776 --- /dev/null +++ b/Writerside/topics/Json.md @@ -0,0 +1,42 @@ +# JSON + +```bash +sudo cpanm JSON +``` + +[JSON - JSON (JavaScript Object Notation) encoder/decoder - metacpan.org](https://metacpan.org/pod/JSON) + +## 문자열을 해시로 변환 + +```perl +#! /usr/bin/perl +use strict; +use JSON; + +my $json = <{'name'}\n"; +print "AGE: $obj->{'age'}\n"; +``` + +`decode_json`은 매개변수로 문자열을 전달받고, 변환 결과인 해시에 대한 참조를 반환합니다. + +## 해시를 문자열로 변환 + +```perl +#! /usr/bin/perl +use strict; +use JSON; + +my %person = ('name'=>'Steve', 'age'=>34); +my $text = &encode_json(\%person); # pass a reference to a hash +print "JSON TEXT: $text\n"; +``` + +`encode_json`은 해시에 대한 참조를 매개변수로 전달 받고, 변환 결과를 문자열로 반환합니다. \ No newline at end of file diff --git a/Writerside/topics/Loop.md b/Writerside/topics/Loop.md new file mode 100644 index 0000000..00520e2 --- /dev/null +++ b/Writerside/topics/Loop.md @@ -0,0 +1,99 @@ +# 반복문 + +## for … / foreach … + +```perl +#!/usr/bin/perl +use warnings; +use strict; + +my @array = (0..9); +for (@array) { + print ("$_", "\n"); +} +``` + +`$_`는 반복자라고 불리는 특수 변수입니다. 반복자를 명시하지 않으면 $_라는 특수 변수가 사용됩니다. 다음과 같이 반복자를 명시할 수도 있습니다. + +```perl +for my $i (@array) { + print ("$i", "\n"); +} +``` + +반복자의 값을 변경하면 배열의 요소에도 변경된 값이 적용됩니다. + +```perl +my @array = (0..9); +for (@array) { + $_ = $_ +1; +} +print "@array\n"; +``` + +C-스타일의 for 구문도 사용할 수 있습니다. + +```perl +my @array = (0..9); +for (my $i=0; $i<=$#array; $i++) { + print ("$array[$i]", "\n"); +} +``` + +## while … + +```perl +print "$i++\n" while ($i > 0); +``` + +```perl +while (my $input = ) { + chomp $input; +} +``` + +## do … while … + +```perl +do { + ... +} while (...); +``` + +## until … + +```perl +until(...) { + ... +} +``` + +## do … until … + +```perl +do { + ... +} until (...); +``` + +## 흐름 제어 + +### next + +C 언어의 continue와 비슷합니다. + +```perl +while (...){ + next if (...); +} +``` + +### last + +C 언어의 break와 비슷합니다. + +```perl +while (...){ + last if (...); +} +``` \ No newline at end of file diff --git a/Writerside/topics/Module.md b/Writerside/topics/Module.md new file mode 100644 index 0000000..7cbd37d --- /dev/null +++ b/Writerside/topics/Module.md @@ -0,0 +1,68 @@ +# 모듈 + +PERL의 모듈은 확장자로 __.pm__을 사용합니다. + +모듈은 *package* 선언으로 시작됩니다. + +```perl +package MyTest; +# MyTest.pm +use warnings; +use strict; + +my $var = 1; + +sub say_hello { + return "Hello"; +} +1; +``` + +스크립트에서 다른 모듈을 사용하려면 `use`등을 사용해서 사용하려는 모듈을 선언해야 합니다. + +```perl +#!/usr/bin/perl +use warnings; +use strict; +use lib '/home/elex/Workspace/perl-examples'; # @INC에 모듈의 경로를 알려주기 위해 사용되었습니다. +use MyTest; # 사용할 모듈을 불러온 다음, + +$a = MyTest::say_hello(); # 모듈의 서브루틴을 호출합니다. + +print "$a\n"; +``` + +- do + + `@INC`에 정의된 경로에서 모듈 파일을 찾고, 찾은 모듈을 삽입합니다. + +- require + + 모듈을 한 번만 불러옵니다. 모듈을 찾지 못하면 오류가 표시됩니다. + +- use + + require와 비슷하지만, 프로그램 실행 전에 모듈을 불러옵니다. 대부분의 경우, use가 사용됩니다. + + +## BEGIN 블록과 END 블록 + +BEGIN 블록은 스크립트가 로딩된 직후에 다른 실행문이 실행되기 이전에 실행됩니다. END 블록은 스크립트가 실행을 마친 직후에 실행됩니다. + +```perl +#!/usr/bin/perl +use strict; + +package Foo; + +sub hello { + print 'Hello.'; +} +BEGIN { + print 'Begin..'; +} +END { + print '..End.'; +} +1; +``` \ No newline at end of file diff --git a/Writerside/topics/OOP.md b/Writerside/topics/OOP.md new file mode 100644 index 0000000..b857367 --- /dev/null +++ b/Writerside/topics/OOP.md @@ -0,0 +1,103 @@ +# OOP + +PERL의 클래스는 package입니다. 객체는 참조가, 메서드는 서브루틴입니다. + +```perl +package Person; + +use warnings; +use strict; + +# 생성자 +sub new { + my ($class, $args) = @_; + my $self = bless { + name => $args->{name}, + age => $args->{age} + }, $class; # bless()는 객체에 대한 참조를 반환합니다. +} + +sub get_name { + my $self = shift; + return $self->{name}; +} + +sub set_name { + my ($self, $name) = @_; + $self->{name} = $name; +} + +sub get_age{ + my $self = shift; + return $self->{age}; +} + +sub set_age{ + my ($self, $age) = @_; + $self->{age} = $age; +} + +sub to_string { + my $self = shift; + return "($self->{name}, $self->{age})"; +} + +sub DESTROY { # 파괴자 + ... +} + +1; # 클래스 정의의 맨 끝에서 true를 반환해줘야 합니다. +``` + +```perl +package Employee; # Person 클래스를 상속할 겁니다. + +use warnings; +use strict; +use lib '/home/elex/Workspace/perl-examples'; +use Person; + +our @ISA = qw(Person); # Person을 상속. IS-A 관계 + +sub new { + my ($class, $args) = @_; + my $self = $class->SUPER::new( $_[1], $_[2] ); # 부모 생성자 호출 + $self->{id} = $args->{id}; + bless $self, $class; + return $self; +} + +sub get_id{ + my $self = shift; + return$self->{id}; +} + +sub set_id{ + my ($self, $id) = @_; + $self->{id} = $id; +} + +sub do_work{ + return "working.."; +} + +sub to_string { + my $self = shift; + return "($self->{name}, $self->{age}, $self->{id})"; +} +``` + +```perl +#!/usr/bin/perl +use warnings; +use strict; +use lib '/home/elex/Workspace/perl-examples'; +use Person; + +# 객체 생성 +my $charlie = Person->new({ + name => 'Charlie', age => 14 +}); +# 메서드 호출 +print $charlie->to_string()."\n"; +``` \ No newline at end of file diff --git a/Writerside/topics/Operator.md b/Writerside/topics/Operator.md new file mode 100644 index 0000000..f7d9852 --- /dev/null +++ b/Writerside/topics/Operator.md @@ -0,0 +1,80 @@ +# 연산자 + +## 산술 연산자 + +| 연산자 | 내용 | +| --- | --- | +| + | 더하기 | +| - | 빼기 | +| * | 곱하기 | +| / | 나누기 | +| % | 나머지 | +| ** | 거듭제곱 | +| ++ | | +| – | | + +## 비교 연산자 + +| 연산자 | 문자열 연산자 | 내용 | +| --- | --- | --- | +| == | eq | 같다 | +| != | ne | 다르다 | +| <=> | cmp | 비교 결과를 -1, 0, 1로 반환 | +| > | gt | 크다 | +| < | lt | 작다 | +| >= | ge | 크거나 같다 | +| <= | le | 작거나 같다 | + +## 할당 연산자 + +| 연산자 | 내용 | +| --- | --- | +| = | | +| += | | +| -= | | +| *= | | +| /= | | +| %= | | +| **= | | + +## 비트 연산자 + +| 연산자 | 내용 | +| --- | --- | +| & | | +| \\| | | +| ^ | | +| ~ | | +| << | | +| >> | | + +## 논리 연산자 + +| 연산자 | 연산자 | 내용 | +| --- | --- | --- | +| and | && | | +| or | \\|\\| | | +| not | | | + +## 따옴표 연산자 + +| 연산자 | 내용 | | | +| --- | --- | --- | --- | +| q// | 홑 따옴표 | q/abcd/ | 'abcd' | +| qq// | 겹 따옴표 | qq/abcd/ | "abcd" | +| qx// | 백틱 따옴표 | qx/abcd/ | \`abcd` | + +## 문자열 연산자 + +| 연산자 | 내용 | | | +| --- | --- | --- | --- | +| . | 문자열 결합 | | | +| x | 문자열 반복 | '-' x 3 | '---' | +| .= | | | | + +## 그 외 + +| 연산자 | 내용 | +| --- | --- | +| .. | 범위 연산자 | +| -> | 객체의 멤버 변수나 메서드 참조 | \ No newline at end of file diff --git a/Writerside/topics/POD.md b/Writerside/topics/POD.md new file mode 100644 index 0000000..f84fbd1 --- /dev/null +++ b/Writerside/topics/POD.md @@ -0,0 +1,26 @@ +# POD + +```perl +#!/usr/bin/perl +use warnings; +use strict; + +print "Hello, World!"; + +while(){ + print $_; +} + +__END__ + +=head1 'Hello World' Program +=over 4 +=item * option 1 +=item * option 2 +=back +=cut +``` + +```bash +pod2html xxxx.pl +``` \ No newline at end of file diff --git a/Writerside/topics/Reference.md b/Writerside/topics/Reference.md new file mode 100644 index 0000000..dfefbab --- /dev/null +++ b/Writerside/topics/Reference.md @@ -0,0 +1,62 @@ +# 참조 + +PERL에서 참조는 다른 스칼라, 배열, 해시 등을 가리키는 스칼라 타입의 변수입니다. 참조는 스칼라 타입이기 때문에, 배열이나 해시의 구성 요소로 사용될 수 있으며, 이를 통해 다차원 배열 등 복잡한 자료 구조를 만들 수 있습니다. + +참조하고자하는 변수 앞에 `\`를 붙이면 해당 변수에 대한 참조가 됩니다. 참조 변수에서 다시 일반 변수를 가져오려면 스칼라 형 앞에 `$`, 배열인 경우에는 `@`, 해시는 `%`, 서브루틴은 `&`를 붙여주면 됩니다. + +```perl +my $var = 100; +my $var_ref = \$var; + +$$var_ref = $$var_ref * 2; + +print "$var\n"; +print "$$var_ref\n"; # 또는 ${$var_ref} +print "$var_ref\n"; +``` + +참조 배열의 아이템에 접근하려면 `->[]`를 사용합니다. + +```perl +my @array = (1..5); +my $array_ref = \@array; + +my $i=0; +for (@$array_ref) { + print "$$array_ref[$i]\n"; # 또는, $array_ref->[$i] + $i++; +} +``` + +참조 해시의 아이템에 접근하려면 `->{}`를 사용합니다. + +```perl +my %ages = ('Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22); +my $ref = \%ages; + +for (keys %$ref){ + print "$_ = $ref->{$_}\n"; +} +``` + +## 익명 참조 + +참조할 변수를 생성하지 않고 직접 참조를 생성하는 것을 익명 참조라고 부릅니다. `()` 데신에 `[]`나 `{}`를 사용해서 선언합니다. + +```perl +my $array_ref = [1..5]; + +my $hash_ref = {'Charlie'=> 14, 'Steve'=> 37, 'Jane'=> 22}; +``` + +## 심볼릭 참조 + +심볼릭 참조를 사용하려면 `use strict` 옵션을 꺼야합니다. + +```perl +my $ref = "var"; # var는 나중에 변수 이름으로 사용될 예정입니다. + +$$ref = "Hello"; + +print "$var\n"; +``` \ No newline at end of file diff --git a/Writerside/topics/Regular-Expression.md b/Writerside/topics/Regular-Expression.md new file mode 100644 index 0000000..eefab87 --- /dev/null +++ b/Writerside/topics/Regular-Expression.md @@ -0,0 +1,87 @@ +# 정규표현식 + +- m// +- s/// +- tr/// + +## 일치 + +문자열이 정규표현식과 일치하는지 여부를 테스트하려면, `=~` 연산자를 사용합니다. 일치하는 경우에 true가 됩니다. + +```perl +my $str = "Hello, World."; +if ($str =~ /lo/){ + print "matches.\n"; +} else { + print "not matches.\n"; +} +``` + +일치하지 않는 경우를 판단하려면, `!~` 연산자를 사용합니다. + +```perl +my @array = ('Charlie', 'Steve', 'Jane'); +for (@array){ + print "$_\n" if ($_ !~ /an/); +} +``` + +정규표현식에 '/'가 포함된 경우에는 이스케잎 처리하거나, 또는 문자열 앞에 `m`을 붙여 정규표현식임을 나타낼 수도 있습니다. + +```perl +print "$_\n" if ($_ =~ m"an"); +``` + +정규표현식 뒤에 `i`를 붙이면 대소문자를 구분하지 않습니다. + +```perl +print "$_\n" if ($_ =~ /an/i); +``` + +## 그룹 + +일치된 그룹은 특수 변수인 `$1`, `$2` 등을 통해서 사용할 수 있습니다. + +```perl +my @array = ( + "Charlie's phone number is 010-1234-5678.", + "010-9876-5432 is a phone number of Steve.", + "To call Jane, press 010-5555-1234."); +for (@array){ + print "$1\n" if ($_ =~ /(\d{3}-\d{4}-\d{4})/); +} +``` + +## 치환 + +`s/정규표현식/새로운문자열/` 형식의 문법을 사용해서 일치되는 문자열을 다른 문자열로 치환할 수 있습니다. 처음으로 일치된 문자열이 새로운 문자열로 치환됩니다. 모든 일치된 문자열에 대해서 치환하려면 정규표현식 맨 끝에 `g`를 붙입니다. 치환된 문자열의 개수가 반환됩니다. + +```perl +my $var = 'new work city'; +$var =~ s/new work/New York/; + +print "$var\n"; +``` + +```perl +my $var = 'This dog is my dog, not your dog.'; +$var =~ s/dog/duck/g; + +print "$var\n"; +``` + +```perl +my $var = 'This dog is my dog, not your dog.'; +my $count = ($var =~ s/dog/duck/g); # 치환된 문자열 개수를 반환 + +print "$var\n"; +``` + +## 문자 단위 변환 + +`tr///`는 어떤 문자를 다른 문자로 바꿀 때 사용됩니다. 문자 단위로 적용됩니다. + +```perl +$var =~ tr/d,/D./; +# 'd'는 'D'로, ','는 '.'으로 바꿉니다. +``` \ No newline at end of file diff --git a/Writerside/topics/Sendmail.md b/Writerside/topics/Sendmail.md new file mode 100644 index 0000000..144bdba --- /dev/null +++ b/Writerside/topics/Sendmail.md @@ -0,0 +1,84 @@ +# Mail + +```perl +#!/usr/bin/perl + +$to = 'abcd@gmail.com'; +$from = 'webmaster@yourdomain.com'; +$subject = 'Test Email'; +$message = 'This is a test email sent.'; + +open(MAIL, "|/usr/sbin/sendmail -t"); + +# Email Header +print MAIL "To: $to\n"; +print MAIL "From: $from\n"; +print MAIL "Subject: $subject\n\n"; +# Email Body +print MAIL $message; + +close(MAIL); +``` + +## Mail::Mailer + +```perl +#!/usr/bin/perl +use warnings; +use strict; + +use Mail::Mailer; + +my $mailer = Mail::Mailer->new('sendmail'); +my %headers = ( + 'To' => 'you@example.com', + 'From' => 'me@example.com', + 'Subject' => 'Sample Mail' +); +$mailer->open(\%headers); +print $mailer "This is the message.\n"; +$mailer->close; +``` + +- new + +- open + +- close + + +## Mail::Send + +```perl +#!/usr/bin/perl +use warnings; +use strict; + +use Mail::Send; + +my $mail = Mail::Send->new; +$mail->set('To', ('you@example.com', 'another@example.com')); +$mail->to('you@example.com'); +$mail->subject('Sample Mail'); +my $fh = $mail->open('sendmail'); +print $fh "This is the message.\n"; +$fh->close or die $!; +``` + +- new + +- open + +- add + +- delete + +- set + +- to + +- cc + +- bcc + +- subject \ No newline at end of file diff --git a/Writerside/topics/Socket.md b/Writerside/topics/Socket.md new file mode 100644 index 0000000..3a5f9a2 --- /dev/null +++ b/Writerside/topics/Socket.md @@ -0,0 +1,114 @@ +# 소켓 + +- socket(소켓, 도메인, 타입, 프로토콜) + + - 도메인: `PF_INET`으로 지정합니다. + + - 타입: TCP/IP 연결을 사용하기 위해서는 `SOCK_STREAM`으로 지정합니다. + + - 프로토콜: `getprotobyname('tcp')` + +- bind(소켓, 어드레스) + + ```perl + bind($socket, pack_sockaddr_in(9999, inet_aton('123.456.789.1'))); + ``` + +- listen(소켓, 큐사이즈) + + - 큐사이즈: 동시 연결 가능한 최대 숫자를 지정합니다. +- accept(클라이언트소켓, 서버소켓) + 일반적으로, 무한 루프 안에서 사용됩니다. + + ```perl + while (1){ + accept($client_socket, $server_socket); + } + ``` + +- connect(소켓, 주소) + +- recv + +- send + +- shutdown, close + +- inet_aton + + 문자열 형식의 주소를 `pack_sockaddr_in()`에 전달하기 위한 바이너리 형식으로 변환합니다. + +- inet_ntoa + +- inet_pton + + 첫 번째 매개변수는 `AF_INET` 또는 `AF_INET6`입니다. + +- inet_ntop + + +## Server + +```perl +#!/usr/bin/perl +use warnings; +use strict; +use Socket; + +my $port = 9999; + +# +my $server; +socket($server, PF_INET, SOCK_STREAM, getprotobyname('tcp')); +bind($server, sockaddr_in($port, INADDR_ANY)) or die $!; +listen($server, 10); +while(1) { + my $client; + my $paddr = accept($client, $server); + my($port, $iaddr) = sockaddr_in($paddr); + my $name = gethostbyaddr($iaddr, AF_INET); + print $client "Smile from the server"; + print "Connection recieved from $name\n"; + close $client; +} +# https://perldoc.perl.org/perlipc#Sockets%3A-Client%2FServer-Communication +``` + +- socket()으로 소켓을 만듭니다. + +- bind()는 소켓과 포트 번호를 연결합니다. + +- listen()을 실행해서 해당 포트에 대해 수신 대기 상태로 만듭니다. + +- accept()를 사용해서 클라이언트와 연결합니다. + + +## Client + +```perl +#!/usr/bin/perl +use warnings; +use strict; +use Socket; + +my $port = 9999; +my $host = "localhost"; + +my $socket; +my $iaddr = inet_aton($host); +my $paddr = sockaddr_in($port, $iaddr); + +socket($socket, PF_INET, SOCK_STREAM, getprotobyname('tcp')); +connect($socket, $paddr) or die $!; + +my $line; +while ($line = <$socket>) { + print "$line\n"; +} +close $socket or die "close: $!"; +exit (0); +``` + +- socket()으로 소켓을 만듭니다. + +- connect()를 통해서 서버 소켓에 연결합니다. \ No newline at end of file diff --git a/Writerside/topics/Subroutine.md b/Writerside/topics/Subroutine.md new file mode 100644 index 0000000..2d02b3b --- /dev/null +++ b/Writerside/topics/Subroutine.md @@ -0,0 +1,76 @@ +# 서브루틴 + +```perl +sub do_something { + print "Hello.\n"; +} + +&do_something; # 또는 do_something(); +``` + +## 매개변수 전달과 결과값의 반환 + +서브루틴의 매개변수는 `@_`라는 특수 변수를 통해서 전달됩니다. + +그리고, `return` 키워드를 통해서 서브루틴의 결과 값을 반환합니다. 만일, 서브루틴에 return 키워드가 없다면 마지막 줄이 반환값이 됩니다. + +```perl +print &do_something('Charlie', 100)."\n"; +sub do_something { + return "Hello, $_[0]. Your number is $_[1]."; + # 또는, "Hello, $_[0]. Your number is $_[1]."; +} +``` + +`@_`는 참조에 의한 전달이므로 서브루틴 내에서 배열의 값을 변경하면, 서브루틴 외부에서도 변경된 상태가 됩니다. 전달된 매개변수의 값이 변경되지 않도록 하려면 별도의 지역 변수에 값을 복사해서 사용해야 합니다. + +```perl +my @var = (1..5); +&do_something(@var); + +print "@var\n"; + +sub do_something { + for (@_){ + $_ += 2; + } +} +``` + +서브루틴은 연산이 실패한 경우 등에 `undef`를 반환할 수 있습니다. 그리고, `defined`를 통해서 변수에 값이 할당되었는지를 판별할 수 있습니다. + +```perl +my $max = &max(3..5); +if (defined $max){ + print "$max\n"; +} else { + print "Oops.\n"; +} + +sub max{ + return undef unless defined $_[0]; + my $val = $_[0]; + for (@_){ + $val = $_ if $val < $_; + } + return $val; +} +``` + +서브루틴의 매개변수로 배열이나 해시를 전달하려면 참조를 사용하면 됩니다. + +```perl +my @var1 = (1..5); +my @var2 = (6..10); +&do_something(\@var1, \@var2); + +sub do_something { + my $ref1 = $_[0]; + my $ref2 = $_[1]; + + $ref1->[0] = 0; + + my @ret = (); + return @ret; +} +``` \ No newline at end of file diff --git a/Writerside/topics/System.md b/Writerside/topics/System.md new file mode 100644 index 0000000..ab686e6 --- /dev/null +++ b/Writerside/topics/System.md @@ -0,0 +1,74 @@ +# 시스템 + +시스템 명령어를 실행하는 가장 쉬운 방법은 백틱으로 감싸는 것입니다. 결과값을 반환 받을 수 있습니다. + +```perl +@files = `ls -al`; +``` + +## eval + +## system + +```perl +system("ls -al"); +``` + +결과값은 화면으로 출력됩니다. + +## fork + +fork()는 프로세스를 복제합니다. 새로 생성된 자식 프로세스는 fork()된 시점부터 진행되며 0을 반환받습니다. 부모 프로세스는 자식 프로세스의 프로세스 번호를 반환 받습니다. 프로세스 생성에 실패한 경우에는 `undef`가 반환됩니다. + +```perl +my $process_id = fork(); +if ($process_id == 0) { + # Child process + print "Child process.\n"; +} else { + # Parent process + print "Parent process.\n"; +} +``` + +생성된 자식 프로세스를 종료하려면 `exit()`를 사용합니다. 자식 프로세스가 모두 종료되기 전에는 메인 프로세스가 종료되지 않습니다. + +```perl +exit(0); +``` + +## 프로세스 + +특수변수인 `$$` 또는 `$PROCESS_ID`를 사용해서 현재 프로세스 번호를 알아낼 수 있습니다. + +- exec + + `system()`과 비슷하지만 명령 실행 전에 현재 프로세스가 종료됩니다. + +- kill + + 프로세스 그룹에 종료 신호를 보냅니다. + + ```perl + kill("INT", @proc_list); + ``` + +- sleep + + ```perl + sleep(5); # 5초 동안 쉽니다. + ``` + +- times + + 프로그램에 소요된 시간을 리스트로 반환합니다. + +- wait + + 자식 프로세스가 종료될 때까지 기다립니다. 자식 프로세스가 없다면 -1이 반환됩니다. + + ```perl + $process_id = wait(); + ``` + +- waitpid \ No newline at end of file diff --git a/Writerside/topics/Variable.md b/Writerside/topics/Variable.md new file mode 100644 index 0000000..e48bea7 --- /dev/null +++ b/Writerside/topics/Variable.md @@ -0,0 +1,79 @@ +# 변수 + +`use strict;`를 선언하면 엄격한 문법을 적용합니다. 이 경우, 모든 변수는 사용하기 전에 선언되어야 합니다. + +```perl +#!/usr/bin/perl + +$var; +``` + +```perl +#!/usr/bin/perl +use strict; + +my $var; +``` + +## 변수의 범위 + +```perl +#!/usr/bin/perl +use warnings; +use strict; + +our $var = 'Charlie'; +print "$var\n"; # Charlie +{ + my $var = 'Steve'; + print "$var\n"; # Steve +} +print "$var\n"; # Charlie +``` + +`my` 는 지역 변수를 선언할 때 사용되는 키워드입니다. 선언된 블록 범위 내에서만 유효합니다. + +`our`는 전역 변수의 선언에 사용되는 키워드입니다. + +## @ARGV + +프로그램 실행시 명령행으로부터 전달 받은 매개변수는 **@ARGV** 배열에 저장됩니다. **$#ARGV + 1**은 전달받은 매개 변수의 갯수입니다. + +```perl +#!/usr/bin/perl +use strict; + +my $size = $#ARGV+1; +print "count = $size\n"; + +for (@ARGV){ + print "$_\n"; +} +``` + +## 특수 변수 + +| | | | +| --- | --- | --- | +| \$_ | | | +| \$. | | | +| \$/ | 입력 레코드 구분자 | | +| \$, | 출력 필드 구분자 | | +| \$\ | 출력 레코드 구분자 | | +| \$" | | | +| \$; | | | +| \$^L | | | +| \$: | | | +| \$^A | | | +| \$# | | | +| \$? | 시스템 콜로부터 돌려받은 상태 코드 | | +| \$! | 오류 넘버 또는 오류 메시지 | | +| \$@ | 구문 오류 메시지 | | +| \$\$ | Perl 프로세스의 PID | | +| \$< | UID | | +| \$> | | | +| \$( | GID | | +| \$) | | | +| \$0 | | | +| | | | +| | | | \ No newline at end of file diff --git a/Writerside/topics/starter-topic.md b/Writerside/topics/starter-topic.md new file mode 100644 index 0000000..e0fa804 --- /dev/null +++ b/Writerside/topics/starter-topic.md @@ -0,0 +1,45 @@ +# Perl + +```bash +sudo apt install perl +``` + +```bash +perl -v +``` + +## + +## cpan + +CPAN은 모듈 관리 프로그램입니다. 최초 실행시에는 설정이 진행되어, 홈 디렉토리에 .cpan과 perl5 디렉토리가 생성되고 PATH가 설정됩니다. + +```bash +cpan +``` + +다음 명령을 사용해서 `cpanm`을 설치합니다. CPANM은 또 다른 모듈 관리 프로그램입니다. + +```bash +cpan App::cpanminus +``` + +또는, + +```bash +sudo apt install cpanminus build-essential +``` + +## cpanm + +```bash +cpanm Tk # 모듈을 설치합니다. +``` + +```bash +cpanm Tk --notest # 테스트 없이 설치합니다. +``` + +```bash +cpanm --uninstall Tk # 설치된 모듈을 제거합니다. +``` \ No newline at end of file diff --git a/Writerside/v.list b/Writerside/v.list new file mode 100644 index 0000000..2d12cb3 --- /dev/null +++ b/Writerside/v.list @@ -0,0 +1,5 @@ + + + + + diff --git a/Writerside/writerside.cfg b/Writerside/writerside.cfg new file mode 100644 index 0000000..5684a1b --- /dev/null +++ b/Writerside/writerside.cfg @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file