2024-06-21

This commit is contained in:
2024-06-21 14:57:07 +09:00
parent 04caa2eb53
commit e00dd1bfbf
43 changed files with 2689 additions and 0 deletions

217
Writerside/topics/Array.md Normal file
View File

@@ -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이 됩니다.

View File

@@ -0,0 +1,8 @@
# Base64
```perl
use MIME::Base64;
$encoded = encode_base64('some text');
$decoded = decode_base64($encoded);
```

162
Writerside/topics/CGI.md Normal file
View File

@@ -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;
}
}
```

View File

@@ -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.";
}
}
```

View File

@@ -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 = <<MYDOC;
$name is $age-year-old.
MYDOC
print $var;
$var = <<"MYDOC"; # 쌍따옴표로 묶은 것은 따옴표로 묶지 않은 것과 같습니다.
$name is $age-year-old.
MYDOC
print $var;
$var = <<'MYDOC'; # 이렇게하면 보간 처리가 되지 않습니다.
$name is $age-year-old.
MYDOC
print $var;
```
#### V-문자열
V-문자열은 v로 시작하며, 문자 코드를 .으로 구분하여 표기합니다.
```perl
$char = v9786;
print "$char\n"; # ☺
$str = v102.111.111;
print "$str\n"; # foo
```
#### 특수 리터럴
다음 특수 리터럴은 `$`도 붙지 않으며, 문자열 보간에는 사용될 수 없습니다. 사실 변수가 아니라 함수입니다.
- `__FILE__`
현재 스크립트 파일 이름
- `__LINE__`
현재 줄 번호
- `__PACKAGE__`
현재 패키지 이름
```perl
print "Line: ".__LINE__."\n";
```
#### 문자열 함수
- length(STRING)
문자열의 길이
- lc(STRING), lcfirst(STRING)
소문자로 변환
- uc(STRING), ucfirst(STRING)
대문자로 변환
- index(STRING, SUBSTR)
부분 문자열의 위치
- rindex(STRING, SUBSTR)
index()와 마찬가지로 부분 문자열의 위치를 반환합니다만, 문자열의 끝에서부터 탐색합니다.
- substr(STRING, OFFSET)
부분 문자열을 반환합니다.
- substr(STRING, OFFSET, LENGTH)
- substr(STRING, OFFSET, LENGTH, NEW_STR)
부분 문자열이 반환되며, 원본 문자열 중 해당 부분이 새로운 문자열로 대체됩니다.
- chr(NUMBER)
아스키 코드 또는 유니코드를 문자로 변환합니다.
- crypt(STRING, SALT)
비밀번호 등의 단방향 암호화에 사용됩니다.
- hex(STRING)
16진수 문자를 변환합니다.
- ord(STRING)
문자열의 첫 번째 문자를 숫자로 변환합니다.
- reverse(STRING)
문자열을 뒤집습니다.
- sprintf(FORMAT_STR, VAR)
C 스타일의 형식화 문자열 함수입니다.
- chop(STRING)
문자열에서 마지막 문자를 제거합니다. 매개변수가 생략된 경우에는 `$_`에 대해서 실행됩니다. 매개변수가 리스트인 경우에는 모든 아이템에 대해서 실행됩니다.
- chomp(STRING)
chop()과 비슷하지만, 문자열에서 마지막 줄바꿈 문자를 제거합니다.
## 리스트
괄호 사이에 스칼라 값을 콤마로 구분하여 나열한 것을 리스트라고 부릅니다. 리스트를 배열 변수에 대입하면 배열이 되고, 해시 변수에 대입하면 해시가 됩니다.
## 배열 (Array)
배열은 0부터 시작되는 숫자 인덱스를 사용하는 순서화된 리스트입니다. 배열 타입의 변수는 `@`로 시작합니다. 배열의 아이템은 스칼라 타입이므로 배열의 아이템을 참조할 때에는 변수명 앞에 `$`를 사용하고, 배열의 인덱스는 `[]`로 명시합니다.
```perl
@names = ('Charlie', 'Steve', 'Jane');
print "$names[0]\n";
```
## 해시 (Hash)
해시는 키/값 형식의 순서없는 자료형으로 연관 배열이라고도 불립니다. 해시 타입의 변수는 `%`로 시작합니다. 해시의 아이템을 참조할 때에는 변수명 앞에 `$`를 사용하며, 데이터의 키는 `{}`를 사용해서 명시합니다.
```perl
%persons = ('Charlie', 14, 'Steve', 37, 'Jane', 22);
print "Age is $persons{'Charlie'}\n";
```

View File

@@ -0,0 +1,178 @@
# DBI
DBI는 데이터베이스에 독립적인 프로그래밍 인터페이스입니다.
```bash
sudo cpanm DBI
```
[DBI - Database independent interface for Perl - metacpan.org](https://metacpan.org/pod/DBI)
## DBD
데이터베이스 드라이버입니다.
```bash
sudo cpanm DBD::xxx
```
- DBD::MariaDB
```bash
sudo apt install libmariadb-dev # 모듈 설치시에 필요합니다.
sudo cpanm DBD::MariaDB
```
- DBD::Pg
- DBD::SQLite
- DBD::Oracle
- DBD::CSV
- DBD::RAM
- DBD::JDBC
- DBD::ODBC
```perl
use DBI;
my @driver_names = DBI->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`

View File

@@ -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);
```
#

View File

@@ -0,0 +1,28 @@
# 오류 처리
- die
메시지를 출력하고 프로세스가 종료됩니다.
- warn
die와 마찬가지로 메시지를 출력하지만, 종료되지는 않습니다.
특수 변수인 `$!`에는 실제 오류 메시지가 들어있습니다.
```perl
if (...){
} else {
die "Error: xxx - $!";
}
```
```perl
open(...) or die "Error: xxx - $!";
```
```perl
warn "xxxx" unless (...);
```

View File

@@ -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

62
Writerside/topics/GUI.md Normal file
View File

@@ -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

109
Writerside/topics/Hash.md Normal file
View File

@@ -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
```

View File

@@ -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";
```

131
Writerside/topics/Http.md Normal file
View File

@@ -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

71
Writerside/topics/IO.md Normal file
View File

@@ -0,0 +1,71 @@
# I/O
## 표준입력
```perl
my $line = <STDIN>;
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 = <FILE>;
```
여러 줄을 한 번에 읽으려면 배열을 사용합니다.
```perl
@lines = <FILE>;
```
대부분의 경우, 아래와 같이 반복문으로 처리합니다.
```perl
open(FILE, '<', 'file.txt') or die $!;
while (<FILE>){
$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);
```

42
Writerside/topics/Json.md Normal file
View File

@@ -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 = <<JSON;
{
"name":"Charlie",
"age":13
}
JSON
my $obj = &decode_json($json); # returns a reference to a hash
print "NAME: $obj->{'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`은 해시에 대한 참조를 매개변수로 전달 받고, 변환 결과를 문자열로 반환합니다.

99
Writerside/topics/Loop.md Normal file
View File

@@ -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 = <STDIN>) {
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 (...);
}
```

View File

@@ -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;
```

103
Writerside/topics/OOP.md Normal file
View File

@@ -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";
```

View File

@@ -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 | '---' |
| .= | | | |
## 그 외
| 연산자 | 내용 |
| --- | --- |
| .. | 범위 연산자 |
| -> | 객체의 멤버 변수나 메서드 참조 |

26
Writerside/topics/POD.md Normal file
View File

@@ -0,0 +1,26 @@
# POD
```perl
#!/usr/bin/perl
use warnings;
use strict;
print "Hello, World!";
while(<DATA>){
print $_;
}
__END__
=head1 'Hello World' Program
=over 4
=item * option 1
=item * option 2
=back
=cut
```
```bash
pod2html xxxx.pl
```

View File

@@ -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";
```

View File

@@ -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'로, ','는 '.'으로 바꿉니다.
```

View File

@@ -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

114
Writerside/topics/Socket.md Normal file
View File

@@ -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()를 통해서 서버 소켓에 연결합니다.

View File

@@ -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;
}
```

View File

@@ -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

View File

@@ -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 | | |
| | | |
| | | |

View File

@@ -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 # 설치된 모듈을 제거합니다.
```