본문 바로가기
Programming/Perl

perl underground 1-1

by NAMP 2009. 4. 30.

원문: http://www.milw0rm.com/papers/88

 

 

my $dotdot = "../../../../../../../../../../../../../../";

## my $dotdot = '../' x 14;                    ## x 사용하기

 

if($ARGV[1]){ $user = $ARGV[1] } else { $user = "IEUser";}

## my $user = shift || 'IEUser'; ## shift 사용하기

 

my @systemroots = ("PUNIX","WINXP");

##  my @systemroots = qw(PUNIX WINXP);     ## qw() 사용하기

 

foreach (@ARGV) {

$host = $1 if ($_=~/-h((.*)\.(.*)\.(.*)\.(.*))/);

$yourip = $1 if ($_=~/-y((.*)\.(.*)\.(.*)\.(.*))/);

$offset = $1 if ($_=~/-o(.*)/);

}

## (.*) 의 사용을 줄인다.

## my ($host) = $_ =~ /(-h\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/;

 

#The two sets of variables are called `package variables' and `lexical variables',

#and they have nothing to do with each other.

 

<<Package Variables>>

        $x = 1

Package variables are what you get if you don't say otherwise.

패키지 변수는 전역적이다. 전역적이라는 말은 프로그램 어디에서도 볼 수 있다는 의미다.

 

full name = $main::x.

 

단지 $x 라고 만 한다면 펄은 현재 패키지라고 간주한다.

현재 패키지? 보통은  main이지만 바꿀수 있다.

        package Mypackage;

 

선언부 이후는의 패키지 이름은   Mypackage이다.

그러면 $x  $Mypackage::x를 의미한다. .

 

 

모듈을 만든다면 앞에 다음과 같능 문장을 넣을것이다.

        package MyModule;

 

기억해야 할것. 패키지 변수는 전역변수다.

제대로 사용하려면 full name 을 써야겠죠.

 

Package Variable Trivia

Trivia : 하찮은[사소한] , 잡동사니 정보, 잡학적 지식

 

예를 들어, %ENV라고 하면 ,

현재 패키지가 main이 아니더라도, 펄은 %main::env라고 추측한다.

 

puntuation : 구두점 찍기, 구두법, 구두점, 중단.

 

$DBD::Oracle::x 의 의미는

DBD::Oracle 패키지 안의 변수 x

 

Isaac Newton Olivia Newton-John 이 관계가 없는 것처럼,

Newton::Isaac Newton::John::Olivia 는 관계가 없다.

 

Deceptive :  속이는, 현혹시키는, 믿을 수 없는

 

둘다 Newton으로 시작하지만, 속임수다.

Newton::John::Olivia Newton 패키지가 아니라, Newton::John패키지 안에 있다.

 

Temper: 함부로 변경하다, 위조하다

패키지 변수는 위험하다.

누군가 당신 몰래 변경할 수 있다.

그래서 Perl 5 에 전역적이지 않은 새로운 변수를 더했다.

 

Lexical : 어휘의, 사전(편집), 사전적인

<<Lexical Variables>>

항상 my.와 함께 선언되기 때문에 때때로 my variables 이라 불린다.

local variable'을 원한다면 local 이 아니라, my 를 생각하세요

 

선언       my $x;

다음과 같이 선언, 초기화를 할 수 있다.      my $x = 119;

여러 개를 한번에              my ($x, $y, $z, @args) = (5, 23, @_);

 

다음 서브 루틴을 보면,

             sub print_report {

               @employee_list = @_;

               foreach $employee (@employee_list) {

                 $salary = lookup_salary($employee);

                 print_partial_report($employee, $salary);

               }

             }

 

두 명의 프로그러머가 각각 print_report lookup_salary 함수를 만들 때 같은 변수를 사용하는 일이 없어야 한다.

해결책    :  my 변수 사용하기

 

             sub print_report {

               my @employee_list = @_;

               foreach my $employee (@employee_list) {

                 my $salary = lookup_salary($employee);

                 print_partial_report($employee, $salary);

               }

             }

 

my @employee_list print_report 바깥에서는 볼 수 없다.

my 변수는 패키지 변수가 아니다. 패키지 변수의 부분도 아니다.

 

             my $x = 17;

 

             package A;

             $x = 12;

 

             package B;

             $x = 20;

 

             # $x is now 20.

             # $A::x $B::x 는 여전히 정의되지 않았다.

my $x = 17 의 선언은 파일 전체의 범위를 가지는 새로운 렉시컬 변수를 생성한다.

 

package A 는 현재 패키지를 바꾸지만, $x는 렉시컬 변수이기 때문에

$x=12 $A::x 에 영향을 주지 못한다.

마찬가지로 package B 에서도  

$x=20 는 렉시컬 변수를 바꾼다.

 

만약 $main::x, $A::x, $B::x 를 사용하고 싶다. 전체 이름을 사용하라.

 

Package variables are global variables.

For private variables, you must use my.

 

bizarre: 별난, 기묘한, 이상한, 기괴한,

 

my local 을 사용하려고 한다면, 항상 my를 써라.

 

다음 코드는 x=1 50번 찍는다.

             for (1 .. 50) {

               my $x;

               $x++;

               print "x=$x\n";

             }

 

위의 경우, 선언부가 밖에 있어야 원하는 동작을 한다.

             { my $x;

               for (1 .. 50) {

                 $x++;

                 print "x=$x\n";

               }        

             }

            

 

위의 코드는 x=1, x=2, x=3, ... x=50 를 찍는다.

             $seed = 1;

             sub my_rand {

               $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;

               return $seed;

             }

결과는, 아래와 같다.

             16838

             14666

             10953

             11665

             7451

             26316

             27974

             27550

 

여기서 문제점은, $seed 가 전역변수라는 것이다.

누군가 변경할 수 있다는 의미다.

 

함수 안에서 $seed  my variable 로 선언 할 수는 없다.

             sub my_rand {

               my $seed;

               $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;

               return $seed;

             }

 

그렇게 하면, 항상 초기화 될 것다.

 

해결책

             { my $seed = 1;

               sub my_rand {

                 $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;

                 return $seed;

               }

             }

 

선언을 함수 밖에서 하면 한번만 하면 된다. 그리고 블록을 만들어서 블록 안에서만 접근하도록 한다.

 

아래와 같이 해도 된다.

             foreach my $i (@list) {

             for (my $i=0; $i<100; $i++) {

 

만약에 my를 쓰지 않고, 그냥,,, 했다면,

             sub function {

               $x = 42;              # Oops, should have been my $x = 42.

             }

global package variable $x를 바꿀 것이다.

만약 그 변수를 다른 곳에서 사용하고 있다면, GG

 

             use strict 'vars'; 

위의 문장을 넣으면, $x=42 라고 했을 때, 컴파일 에러가 발생한다.

 

             Global symbol "$x" requires explicit package name at ...

 

에러난 곳으로 가서, my를 붙인다.

전역번수로 사용하고 싶다면, 다음과 같은 모습으로 고친다.

             $main::x = 42;

See perldoc strict for more details.

 

 

다음과 같이 , strict vars 에서 예외를 만들 수 있다.

             package Algorithms::KnuthBendix;

             use vars '$Error';

 

다음과 같이 블록을 사용하여 strict vars 를 사용하지 않을 수 도 있다.

             { no strict 'vars';

               # strict vars is off for the rest of the block.

             }

 

전역변수 사용을 피하라.

실수로 전역변수를 사용하는 것을 방지하기 위해

Use strict 'vars' 를 사용하라

'Programming > Perl' 카테고리의 다른 글

perl underground 1-3  (0) 2009.05.02
perl underground 1-2  (0) 2009.05.01
Package  (0) 2009.04.23
OOP&Libraray&Module  (0) 2009.04.23
Perl 파일 다루기  (0) 2009.04.23

댓글