Perl 실행 방법
Perl 실행 방법 (perlrun)
Perl 인터프리터를 어떻게 실행하는지, 그리고 명령행 스위치 하나하나가 정확히 무엇을 하는지 상세히 다루는 문서예요. 원라이너를 자주 쓰거나 스크립트를 직접 실행 가능하게 만들어야 한다면 꼭 읽어야 할 지침이죠.
실행 방법 (SYNOPSIS)
perl [ -gsTtuUWX ] [ -h?v ] [ -V[:configvar] ] [ -cw ] [ -d[t][:debugger] ] [ -D[number/list] ] [ -pna ] [ -Fpattern ] [ -l[octal] ] [ -0[octal/hexadecimal] ] [ -Idir ] [ -m[-]module ] [ -M[-]'module...' ] [ -f ] [ -C [number/list] ] [ -S ] [ -x[dir] ] [ -i[extension] ] [ [-e|-E] 'command' ] [ -- ] [ programfile ] [ argument ]...
개요 (DESCRIPTION)
Perl 프로그램을 실행하는 일반적인 방법은 그 프로그램을 직접 실행 가능하게 만들거나, 소스 파일 이름을 명령행 인자로 넘기는 거예요. (대화형 Perl 환경도 가능해요 — 자세한 건 perldebug를 보세요.) 시작할 때 Perl은 다음 장소 중 한 곳에서 프로그램을 찾아요:
- 명령행의
-e/-E스위치로 줄 단위로 지정된 것 - 명령행의 첫 번째 파일 이름이 가리키는 파일 (참고:
#!표기를 지원하는 시스템은 이렇게 인터프리터를 호출해요. "Perl의 위치" 참고) - 표준 입력을 통해 암묵적으로 전달된 것. 파일 이름 인자가 없을 때만 동작해요 — STDIN으로 읽는 프로그램에 인자를 넘기려면 프로그램 이름에 명시적으로
-를 지정해야 해요.
방법 2·3에서 Perl은 입력 파일을 처음부터 파싱해요. 단, -x 스위치를 지정했다면 #!로 시작하고 "perl" 단어를 포함한 첫 줄을 찾아 거기서부터 시작해요. 커다란 메시지에 내장된 프로그램을 실행할 때 유용해요. (이 경우 프로그램 끝을 __END__ 토큰으로 표시해요.)
#! 줄은 파싱되면서 항상 스위치 검사를 받아요. 그래서 #! 줄에 인자 하나만 허용하는 머신이거나, 더 나쁘게 #! 줄을 아예 인식하지 못하는 머신에서도, -x로 프로그램 시작을 찾았든 상관없이 Perl이 어떻게 호출되든 일관된 스위치 동작을 얻을 수 있어요.
역사적으로 일부 OS가 32자 뒤의 #! 줄 커널 해석을 조용히 잘라 버렸기 때문에, 어떤 스위치는 명령행으로 전달되고 어떤 건 안 될 수 있어요. 조심하지 않으면 글자 없는 -만 남을 수도 있어요. 모든 스위치를 그 32자 경계 앞이나 뒤에 배치하는 게 좋아요. 대부분의 스위치는 중복 처리돼도 신경 안 쓰지만, 완전한 스위치 대신 -가 생기면 Perl이 프로그램 대신 표준 입력을 실행하려 들 수 있어요. 부분적인 -I 스위치도 이상한 결과를 낼 수 있어요.
일부 스위치는 두 번 처리되는 걸 신경 써요. 예를 들어 -l과 -0의 조합이에요. 모든 스위치를 32자 경계 뒤에 두거나(해당된다면), -0digits 사용을 BEGIN{ $/ = "\0digits"; }로 바꾸세요.
#! 스위치 파싱은 줄에서 "perl"이 언급되는 곳에서 시작해요. 시퀀스 -*와 - 는 특별히 무시돼서, 원하면 이렇게 써서 Perl이 -p 스위치를 보게 할 수 있어요:
#!/bin/sh
#! -*- perl -*- -p
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
env 프로그램이 있으면 비슷한 트릭을 쓸 수 있어요:
#!/usr/bin/env perl
위 예시는 perl 인터프리터에 상대 경로를 써서 사용자의 PATH에서 첫 번째 버전을 가져와요. 특정 버전(예: perl5.14.1)을 원하면 그걸 #! 줄 경로에 직접 넣어야 해요.
#! 줄에 "perl"이라는 단어도 "indir"이라는 단어도 없으면, #! 뒤에 이름 붙은 프로그램이 Perl 인터프리터 대신 실행돼요. 약간 이상하지만 #!를 안 하는 머신의 사람들을 도와줘요. SHELL이 /usr/bin/perl이라고 프로그램에 알려 줄 수 있고, Perl이 프로그램을 정확한 인터프리터로 보내 주거든요.
프로그램을 찾은 뒤 Perl은 전체 프로그램을 내부 형태로 컴파일해요. 컴파일 에러가 있으면 프로그램 실행을 시도하지 않아요. (문법 에러를 찾기 전에 일부를 실행해 버릴 수 있는 전형적인 셸 스크립트와 달라요.)
프로그램이 문법적으로 맞으면 실행돼요. exit()나 die() 연산자 없이 끝까지 흘러가면, 성공 완료를 나타내는 암묵적 exit(0)가 제공돼요.
비-Unix 시스템의 #!과 쿼팅
Unix의 #! 기법은 다른 시스템에서 이렇게 흉내 낼 수 있어요:
- OS/2:
*.cmd파일 첫 줄에extproc perl -S -your_switches를 둬요 ("-S"는 cmd.exe의extproc처리 버그 때문이에요). - MS-DOS: 프로그램을 실행하는 배치 파일을 만들고 ALTERNATE_SHEBANG에 고정해요 (소스 배포판의 dosish.h 파일 참고).
- Win95/NT: ActiveState 설치 프로그램으로 Perl을 설치하면 .pl 확장자를 perl 인터프리터와 연결하도록 레지스트리를 수정해요. 다른 방법으로 설치했다면(소스에서 빌드 포함) 레지스트리를 직접 수정해야 할 수도 있어요. 이 말은 실행 가능한 Perl 프로그램과 Perl 라이브러리 파일의 차이를 더 이상 알 수 없다는 뜻이기도 해요.
- VMS: 프로그램 맨 위에
$ perl -mysw 'f$env("procedure")' 'p1' ...같은 것을 둬요 (-mysw는 Perl에 넘길 명령행 스위치). 이제perl program으로 직접 호출하거나 DCL 프로시저로@program처럼 호출할 수 있어요.perl "-V:startperl"이라고 하면 Perl이 이 주문을 보여줘요.
비-Unix 시스템의 명령 해석기는 Unix 셸과 쿼팅 개념이 꽤 달라요. 명령 해석기의 특수 문자(*, \, "가 흔함)와 공백·이들을 보호하는 법을 배워야 원라이너를 돌릴 수 있어요 (아래 -e 참고).
어떤 시스템에선 단일 따옴표를 이중 따옴표로 바꿔야 하는데, Unix나 Plan 9에선 그러면 안 돼요. 단일 %를 %%로 바꿔야 할 수도 있어요. 예:
# Unix
perl -e 'print "Hello world\n"'
# MS-DOS, etc.
perl -e "print \"Hello world\n\""
# VMS
perl -e "print ""Hello world\n"""
문제는 이것들 전부 신뢰할 수 없다는 거예요: 명령에 의존하고 둘 다 동작하지 않을 수도 있어요. 4DOS가 명령 셸이면 이게 더 잘 동작할 거예요. Windows NT의 CMD.EXE는 아무도 모르게 표준 Unix 기능을 많이 쑤셔 넣었지만, 쿼팅 규칙 문서를 찾아보려고만 해 봐요. 이 모든 것에 대한 일반 해법은 없어요. 그냥 엉망이에요.
Perl의 위치
Perl은 사용자가 쉽게 찾을 수 있을 때만 유용하다는 말은 당연해 보여요. 가능하면 /usr/bin/perl과 /usr/local/bin/perl 둘 다 실제 바이너리에 대한 심링크가 되게 하는 게 좋아요. 그게 안 되면, 시스템 관리자는 (심링크된) perl과 그 동반 유틸리티를 사용자의 PATH에 보통 있는 디렉터리나 다른 분명하고 편리한 위치에 두는 걸 강력히 권장해요.
이 문서에서 프로그램 첫 줄의 #!/usr/bin/perl은 시스템에서 동작하는 어떤 방법이든 대표할 거예요. 특정 버전에 신경 쓰면 특정 경로를 쓰는 게 좋아요:
#!/usr/local/bin/perl5.14
또는 최소 버전 이상으로 돌리기만 원하면 프로그램 위에 이렇게 두세요:
use v5.14;
명령 스위치 (Command Switches)
모든 표준 명령처럼 한 글자 스위치는 다음 스위치와 함께 뭉칠 수 있어요.
#!/usr/bin/perl -spi.orig # -s -p -i.orig 와 같음
--는 옵션의 끝을 알리고 추가 옵션 처리를 끄는 표시예요. -- 뒤의 인자는 모두 파일 이름·인자로 취급돼요.
스위치는 다음과 같아요.
-0[octal/hexadecimal]
입력 레코드 구분자($/)를 8진수·16진수 숫자로 지정해요. 숫자가 없으면 null 문자가 구분자예요. 다른 스위치가 숫자 앞뒤에 올 수 있어요. 예를 들어 null 문자로 끝나는 파일 이름을 출력하는 find 버전이 있으면:
find . -name '*.orig' -print0 | perl -n0e unlink
특수 값 00은 Perl이 파일을 단락(paragraph) 모드로 slurp하게 해요.
0400 이상 값은 Perl이 파일을 통째로 slurp하게 하지만, 관례상 0777이 보통 이 용도로 쓰여요. -g 플래그가 이에 대한 더 간단한 별칭이에요.
16진수 표기로도 구분자를 지정할 수 있어요: -0xHHH... (H는 유효 16진수). 8진수 형태와 달리 이건 0xFF 너머의 어떤 Unicode 문자든 지정할 수 있어요. 정말 0777 레코드 구분자를 원하면 -0x1FF로 지정하세요. (즉 16진수로만 된 디렉터리 이름에 -x 옵션을 쓰면 Perl이 -0에 16진수를 지정한 걸로 오해하니 못 써요.)
-a
-n이나 -p와 함께 쓰면 자동 분할(autosplit) 모드를 켜요. -n/-p가 만든 암묵적 while 루프의 첫 번째 일로 @F 배열에 암묵적 split 명령이 실행돼요.
perl -ane 'print pop(@F), "\n";'
이건 다음과 같아요:
while (<>) {
@F = split(' ');
print pop(@F), "\n";
}
-F로 다른 구분자를 지정할 수 있어요. -a는 암묵적으로 -n을 설정해요.
-C [number/list]
-C 플래그는 Perl의 일부 Unicode 피처를 제어해요.
주의:
:utf8PerlIO 레이어처럼, 이 플래그나 동등한PERL_UNICODE환경 변수가 켜는 피처들은 입력이 유효 UTF-8인지 검증하지 않고 유효 UTF-8을 만든다고 보장하지도 않아요. 대신 입력이 Perl의 내부 업그레이드 바이트 인코딩으로 제공된다고 가정하고 이 인코딩으로 출력을 제공해요. 이 인코딩은 Perl 문자열에 허용되는 어떤 문자든 인코딩할 수 있는 UTF-8의 상위집합이에요. (EBCDIC 시스템에선 UTF-EBCDIC의 상위집합.) 이로 인해 깨진 Perl 문자열이나 UTF-8에서 유효하지 않은 출력 바이트가 나올 수 있어요. 이 내부 인코딩을 엄격한 UTF-8 형식과 구분하려고 아래에선 utf8이라고 부를게요.
5.8.1부터 -C 뒤에 숫자 또는 옵션 글자 리스트가 올 수 있어요. 글자·숫자 값·효과는 다음과 같아요. 글자를 나열하는 건 숫자를 합하는 것과 같아요.
I 1 STDIN이 utf8로 가정됨
O 2 STDOUT이 utf8이 됨
E 4 STDERR이 utf8이 됨
S 7 I + O + E
i 8 :utf8이 입력 스트림의 기본 PerlIO 레이어
o 16 :utf8이 출력 스트림의 기본 PerlIO 레이어
D 24 i + o
A 32 @ARGV 요소가 utf8로 인코딩된 문자열일 것으로 기대
L 64 보통 "IOEioA"는 무조건이지만, L은 로케일 환경 변수
(내림차순 우선순위로 LC_ALL, LC_CTYPE, LANG)에
조건적으로 만듦 -- 변수가 UTF-8을 나타내면
선택된 "IOEioA"가 적용됨
a 256 ${^UTF8CACHE}를 -1로 설정해 UTF-8 캐싱 코드를
디버깅 모드로 실행
예를 들어 -COE와 -C6은 둘 다 STDOUT·STDERR을 utf8로 켜요. 글자 반복은 중복일 뿐, 누적도 토글도 아니에요.
io 옵션은 메인 프로그램 스코프의 이후 open()(또는 비슷한 I/O 연산)에 :utf8 PerlIO 레이어가 암묵적으로 적용된다는 뜻이에요. 즉 어떤 입력 스트림에서든 utf8이 기대되고 어떤 출력 스트림으로든 utf8이 생성돼요. 이건 그냥 ${^OPEN}으로 설정된 기본이며, open()의 명시적 레이어와 binmode()로 평소처럼 스트림을 조작할 수 있어요. 모듈에서 돌아가는 코드엔 효과가 없어요.
-C 단독(숫자·옵션 리스트 없음) 또는 PERL_UNICODE 환경 변수의 빈 문자열 ""은 -CSDL과 같은 효과예요. 즉 표준 I/O 핸들과 기본 open() 레이어가 utf8이 되지만, 오직 로케일 환경 변수가 UTF-8 로케일을 나타낼 때만요. 이 동작은 Perl 5.8.0의 암묵적(그리고 문제 있는) UTF-8 동작을 따르는 거예요. (perl581delta의 "UTF-8 no longer default under UTF-8 locales" 참고.)
-C0(또는 PERL_UNICODE에 "0")으로 위의 모든 Unicode 피처를 명시적으로 끌 수 있어요.
읽기 전용 마법 변수 ${^UNICODE}는 이 설정의 숫자 값을 반영해요. 이 변수는 Perl 시작 시 설정되고 이후 읽기 전용이에요. 런타임 효과를 원하면 세 인자 open()(perlfunc의 "open" 참고), 두 인자 binmode()(perlfunc의 "binmode" 참고), open 프래그마를 쓰세요.
(5.8.1 이전 Perl에서 -C 스위치는 Unicode 인식 "와이드 시스템 호출" Win32 API를 켜는 Win32 전용 스위치였어요. 이 피처는 실질적으로 쓰이지 않아서 스위치가 "재활용"됐죠.)
참고: Perl 5.10.1부터 -C 옵션을 #! 줄에 쓰면 명령행에도 지정해야 해요. 이 시점엔 표준 스트림이 이미 설정돼 있기 때문이에요. binmode()로 I/O 스트림 인코딩을 설정할 수도 있어요.
-c
Perl이 프로그램 문법을 검사한 뒤 실행 없이 종료하게 해요. 실제로는 BEGIN, UNITCHECK, CHECK 블록과 모든 use 문을 실행해요. 이것들은 프로그램 실행의 밖에서 일어나는 것으로 간주되죠. INIT·END 블록은 건너뛰어져요. 문법 검사가 성공하면 perl은 상태 0으로 종료하고 program syntax OK를 보고해요. 실패하면 감지된 에러를 출력하고 0이 아닌 상태로 종료해요.
-d, -dt
프로그램을 Perl 디버거 아래에서 실행해요. perldebug를 보세요. t를 지정하면 디버거에 디버깅 중인 코드에 스레드가 쓰일 것임을 알리려고 환경에 PERL5DB_THREADED=1이 설정돼요.
-d:MOD[=bar,baz], -dt:MOD[=bar,baz]
프로그램을 Devel::MOD로 설치된 디버깅·프로파일링·추적 모듈의 제어 아래에서 실행해요. 예: -d:DProf는 Devel::DProf 프로파일러로 프로그램을 실행해요. -M 플래그처럼 옵션을 Devel::MOD 패키지에 전달할 수 있고, Devel::MOD::import 루틴이 받아 해석해요. -M처럼 -d:-MOD로 import 대신 unimport를 호출할 수도 있어요. 쉼표로 구분된 옵션 리스트는 = 문자 뒤에 와야 해요. t를 지정하면 디버거에 스레드 사용을 알려요. perldebug를 보세요.
-Dletters, -Dnumber
디버깅 플래그를 설정해요. 이 스위치는 perl 바이너리가 디버깅을 켜고 빌드됐을 때만 활성화돼요. 일반 프로덕션 perl엔 없어요.
예를 들어 perl이 프로그램을 어떻게 실행하는지 보려면 -Dtls를 써요. -Dx는 컴파일된 문법 트리를 나열하고, -Dr는 컴파일된 정규식을 표시해요. 출력 형식은 perldebguts에 설명돼 있어요. 글자 리스트 대신 숫자를 지정할 수도 있어요(예: -D14는 -Dtls와 동등):
1 p 토큰화·파싱 (v와 함께면 파싱 스택 표시)
2 s 스택 스냅샷 (v와 함께면 모든 스택 표시)
4 l 문맥(루프) 스택 처리
8 t 실행 추적
16 o 메서드·오버로딩 해석
32 c 문자열/숫자 변환
64 P 프로파일링 정보, 소스 파일 입력 상태 출력
128 m 메모리·SV 할당
256 f 포맷 처리
512 r 정규식 파싱·실행
1024 x 문법 트리 덤프
2048 u 탠트(taint) 검사
4096 U 비공식, 사용자 해킹 (개인·미공개용 예약)
8192 h 해시 랜덤화 디버그 출력 표시
16384 X 스크래치패드 할당
32768 D 정리하기
65536 S Op 슬래브 할당
131072 T 토큰화
262144 R 덤프된 변수의 참조 카운트 포함 (예: -Ds 사용 시)
524288 J package DB 내 opcode에서 s,t,P-디버그 표시
1048576 v 상세: 다른 플래그와 함께 사용해 출력 상세 증가
2097152 C Copy On Write
4194304 A 내부 구조의 일관성 검사
8388608 q 조용히 - 현재는 "EXECUTING" 메시지만 억제
16777216 M 스마트 매치 해석 추적
33554432 B BEGIN 같은 특수 블록 포함 서브루틴 정의 덤프
67108864 L 로케일 관련 정보 추적
134217728 i PerlIO 레이어 처리 추적 (PERLIO_DEBUG로 파일 지정)
268435456 y y///, tr/// 컴파일·실행 추적
이 플래그들은 전부 Perl 실행 파일을 컴파일할 때 -DDEBUGGING이 필요해요 (그런데 Devel::Peek의 :opd나 re의 'debug' 모드가 이를 바꿀 수 있어요). 방법은 Perl 소스 배포판의 INSTALL 파일을 보세요.
sh -x가 셸 스크립트에 제공하는 것처럼 실행되는 각 줄을 출력만 하려는 거라면 Perl의 -D 스위치를 못 써요. 대신 이렇게 해요:
# "env" 유틸리티가 있으면
env PERLDB_OPTS="NonStop=1 AutoTrace=1 frame=2" perl -dS program
# Bourne shell 문법
$ PERLDB_OPTS="NonStop=1 AutoTrace=1 frame=2" perl -dS program
# csh 문법
% (setenv PERLDB_OPTS "NonStop=1 AutoTrace=1 frame=2"; perl -dS program)
자세한 내용과 변형은 perldebug를 보세요.
-e commandline
프로그램 한 줄을 입력하는 데 써요. -e가 주어지면 Perl은 인자 리스트에서 파일 이름을 찾지 않아요. 여러 -e 명령으로 다중 줄 스크립트를 만들 수 있어요. 일반 프로그램에서처럼 세미콜론을 쓰는 걸 잊지 마세요.
-E commandline
-e처럼 동작하되, 모든 선택 피처와 내장 함수를 (메인 컴파일 단위에서) 암묵적으로 활성화해요. feature와 builtin을 보세요.
-f
시작 시 $Config{sitelib}/sitecustomize.pl 실행을 끄는 옵션이에요.
Perl은 기본적으로 시작 시 (BEGIN 블록에서) $Config{sitelib}/sitecustomize.pl을 실행하려고 시도하도록 빌드될 수 있어요. 이건 시스템 관리자가 Perl 동작을 커스터마이즈하게 하는 훅이에요. 예를 들어 @INC 배열에 항목을 추가해 Perl이 비표준 위치에서 모듈을 찾게 할 수 있어요. Perl은 실제로 다음 코드를 넣어요:
BEGIN {
do { local $!; -f "$Config{sitelib}/sitecustomize.pl"; }
&& do "$Config{sitelib}/sitecustomize.pl";
}
실제 do(require 아님)라서 sitecustomize.pl은 참 값을 반환할 필요가 없어요. 코드는 package main, 자기 어휘 스코프에서 실행돼요. 하지만 스크립트가 죽으면 $@는 설정되지 않아요. $Config{sitelib} 값도 C 코드에서 결정되고, 로드되지 않은 Config.pm에서 읽지 않아요.
코드는 매우 일찍 실행돼요. 예를 들어 @INC의 어떤 변경이든 perl -V 출력에 나타나요. 물론 END 블록은 아주 늦게 실행돼요. 이 능력이 perl에 컴파일됐는지 런타임에 알려면 $Config{usesitecustomize} 값을 확인하세요.
-Fpattern
-a를 위한 split 패턴을 지정해요. 패턴은 //, "", ''로 감쌀 수 있고, 그 외엔 단일 따옴표에 들어가요. 패턴에 리터럴 공백이나 NUL 문자는 못 써요. -F는 암묵적으로 -a와 -n 둘 다 설정해요.
-g
입력 레코드 구분자($/)를 undef로 만들어 slurp 모드를 켜요. 즉 Perl이 줄 단위 대신 파일 전체를 한 번에 읽게 해요. 이 플래그는 -0777의 더 간단한 별칭이에요. 연상 기호: gobble, grab, gulp.
-h, -?
옵션 요약을 출력해요. -?는 -h의 동의어예요.
-i[extension]
<> 구조가 처리하는 파일을 제자리에서 편집하도록 지정해요. 입력 파일 이름을 바꾸고, 원래 이름으로 출력 파일을 열고, 그 출력 파일을 print() 문의 기본으로 선택해요. 확장자가 주어지면 옛 파일 이름을 수정해 백업 복사본을 만드는 데 써요. 규칙은:
- 확장자가 없고 시스템이 지원하면, 원래 파일은 이름 없이 열린 채 유지되고 출력은 원래 파일 이름의 새 파일로 리다이렉트돼요. perl이 깔끔하든 아니든 종료하면 원래 파일은 unlink돼요.
- 확장자에
*가 없으면 현재 파일 이름 끝에 접미사로 붙어요.*가 하나 이상 있으면 각*가 현재 파일 이름으로 바뀌어요. Perl 용어로는:
($backup = $extension) =~ s/\*/$file_name/g;
이렇게 하면 접미사 대신(또는 추가로) 백업 파일에 접두사를 붙일 수 있어요:
$ perl -pi'orig_*' -e 's/bar/baz/' fileA # 'orig_fileA'로 백업
심지어 원래 파일의 백업 복사본을 다른 디렉터리에 둘 수도 있어요(디렉터리가 이미 존재한다면):
$ perl -pi'old/*.orig' -e 's/bar/baz/' fileA # 'old/fileA.orig'
다음 원라이너 셋은 동등해요:
$ perl -pi -e 's/bar/baz/' fileA # 현재 파일 덮어씀
$ perl -pi'*' -e 's/bar/baz/' fileA # 현재 파일 덮어씀
$ perl -pi'.orig' -e 's/bar/baz/' fileA # 'fileA.orig'로 백업
$ perl -pi'*.orig' -e 's/bar/baz/' fileA # 'fileA.orig'로 백업
셸에서:
$ perl -p -i.orig -e "s/foo/bar/; ... "
이건 프로그램:
#!/usr/bin/perl -pi.orig
s/foo/bar/;
과 같고, 이건 다음과 동등해요:
#!/usr/bin/perl
$extension = '.orig';
LINE: while (<>) {
if ($ARGV ne $oldargv) {
if ($extension !~ /\*/) {
$backup = $ARGV . $extension;
}
else {
($backup = $extension) =~ s/\*/$ARGV/g;
}
rename($ARGV, $backup);
open(ARGVOUT, ">$ARGV");
select(ARGVOUT);
$oldargv = $ARGV;
}
s/foo/bar/;
}
continue {
print; # 이건 원래 파일 이름으로 출력
}
select(STDOUT);
차이는 -i 형태가 파일 이름이 바뀌었는지 알기 위해 $ARGV를 $oldargv와 비교할 필요가 없다는 거예요. 그 대신 선택된 파일핸들로 ARGVOUT을 써요. 루프 후 STDOUT이 기본 출력 파일핸들로 복원된다는 걸 주목하세요.
위처럼 Perl은 출력이 실제로 바뀌었는지와 무관하게 백업 파일을 만들어요. 그래서 이건 파일을 복사하는 화려한 방법이에요:
$ perl -p -i'/some/file/path/*' -e 1 file1 file2 file3...
or
$ perl -p -i'.orig' -e 1 file1 file2 file3...
각 파일에 append하거나 줄 번호를 리셋하려면 괄호 없는 eof를 사용해 각 입력 파일의 끝을 찾을 수 있어요 (perlfunc의 "eof" 예시 참고). 주어진 파일에 대해 확장자에 지정된 대로 백업 파일을 만들 수 없으면 Perl은 그 파일을 건너뛰고 다음 파일로 계속해요. 파일 권한과 -i 관련 논의는 perlfaq5의 "Why does Perl let me delete read-only files? Why does -i clobber protected files? Isn't this a bug in Perl?"을 보세요. -i로 디렉터리를 만들거나 파일에서 확장자를 제거할 수는 없어요. Perl은 파일 이름에서 ~를 확장하지 않아요. 어떤 사람은 백업 파일에 쓰므로 좋은 일이에요:
$ perl -pi~ -e 's/foo/bar/' file1 file2 file3...
-i가 새 파일을 만들기 전에 원본을 rename·delete하므로 Unix 스타일 소프트·하드 링크는 보존되지 않아요. 마지막으로 -i 스위치는 명령행에 파일이 없어도 실행을 막지 않아요. 그 경우 백업은 만들어지지 않고(원본을 당연히 알 수 없음) STDIN→STDOUT으로 처리가 진행돼요.
-Idirectory
-I로 지정한 디렉터리는 모듈 검색 경로(@INC) 앞에 붙어요.
-l[octnum]
자동 줄 끝 처리를 켜요. 두 가지 별개 효과가 있어요. 첫째, -n/-p와 함께 쓰면 $/(입력 레코드 구분자)를 자동으로 chomp해요. 둘째, $\(출력 레코드 구분자)에 octnum 값을 할당해서 모든 print 문에 그 구분자가 다시 붙게 해요. octnum이 생략되면 $\를 $/의 현재 값으로 설정해요. 예를 들어 줄을 80컬럼으로 자르려면:
perl -lpe 'substr($_, 80) = ""'
$\ = $/ 할당은 스위치가 처리될 때 이뤄지므로, -l 뒤에 -0 스위치가 오면 입력 레코드 구분자가 출력 레코드 구분자와 다를 수 있어요:
gnufind / -print0 | perl -ln0e 'print "found $_" if -p'
이건 $\를 줄바꿈으로 설정한 다음 $/를 null 문자로 설정해요.
-m[-]module, -M[-]module, -M[-]'module ...', -[mM][-]module=arg[,arg]...
-mmodule은 프로그램을 실행하기 전에 use module ();을 실행해요. 이건 모듈을 로드하지만 import 메서드를 호출하지 않아서, 서브루틴을 import하지 않고 프래그마도 효과를 못 줘요.
-Mmodule은 프로그램을 실행하기 전에 use module;을 실행해요. 이건 모듈을 로드하고 import 메서드를 호출해서 모듈이 기본 효과(보통 서브루틴 import나 프래그마 효과)를 갖게 해요. 따옴표로 모듈 이름 뒤에 추가 코드를 붙일 수 있어요. 예: '-MMODULE qw(foo bar)'.
-M/-m 뒤 첫 문자가 대시(-)면 'use'가 'no'로 바뀌어요. -m엔 차이가 없어요.
Perl 5.39.8부터 -M 스위치와 모듈 이름을 별도 명령행 인자로 넘길 수 있어요:
perl -M MODULE ... # perl -MMODULE ... 처럼
perl -M MODULE=arg1,arg2,... # perl -MMODULE=arg1,arg2,... 처럼
작은 내장 문법 설탕으로 -mMODULE=foo,bar나 -MMODULE=foo,bar를 '-MMODULE qw(foo bar)'의 단축으로 쓸 수도 있어요. 심볼 import 시 따옴표를 피할 수 있죠. -MMODULE=foo,bar가 실제 생성하는 코드는 use module split(/,/,q{foo,bar})예요. = 형태가 -m과 -M의 구분을 없앤다는 걸 주목하세요. 즉 -mMODULE=foo,bar는 -MMODULE=foo,bar와 같아요. split 공식의 결과로 -MMODULE=number는 MODULE::import() 자체가 버전 검사를 하도록 설정돼 있지 않으면(예: MODULE이 Exporter에서 상속) 절대 버전 검사를 하지 않아요.
-n
Perl이 프로그램 주위에 다음 루프를 가정하게 해요. sed -n이나 awk처럼 파일 이름 인자를 반복하게 하죠:
LINE:
while (<>) {
... # your program goes here
}
줄이 기본적으로 출력되지 않는다는 점을 주의하세요. 출력하려면 -p를 보세요. 인자가 가리키는 파일을 어떤 이유로 열 수 없으면 Perl이 경고하고 다음 파일로 넘어가요. <>는 perlfunc의 "open"에 명령행 인자를 넘기는데, 열려면 반드시 파일 이름으로 해석되진 않아요. 보안 함의는 perlop을 보세요. 일주일 이상 수정되지 않은 모든 파일을 지우는 효율적인 방법:
find . -mtime +7 -print | perl -nle unlink
이건 찾은 파일마다 프로세스를 시작할 필요가 없어 find의 -exec 스위치보다 빨라요 (하지만 최신 find의 -delete 스위치보다 빠르진 않아요). 경로 이름의 줄바꿈을 잘못 처리하는 버그가 있어서 -0 아래 예시를 따라 고칠 수 있어요. BEGIN·END 블록으로 awk처럼 암묵적 프로그램 루프 전·후의 제어를 잡을 수 있어요.
-p
Perl이 프로그램 주위에 다음 루프를 가정하게 해요. sed처럼 파일 이름 인자를 반복하게 하죠:
LINE:
while (<>) {
... # your program goes here
} continue {
print or die "-p destination: $!\n";
}
인자가 가리키는 파일을 어떤 이유로 열 수 없으면 Perl이 경고하고 다음 파일로 가요. 줄이 자동으로 출력된다는 점을 주목하세요. 출력 중 에러는 치명적으로 처리돼요. 출력을 억제하려면 -n 스위치를 써요. -p는 -n을 덮어써요. BEGIN·END 블록으로 awk처럼 암묵적 루프 전·후의 제어를 잡을 수 있어요.
-s
프로그램 이름 뒤, 파일 이름 인자 앞(또는 -- 인자 앞)의 명령행 스위치에 대한 기초적인 스위치 파싱을 켜요. 거기서 찾은 어떤 스위치든 @ARGV에서 제거되고, Perl 프로그램의 main 패키지에 해당 변수를 설정해요. 다음 프로그램은 -xyz 스위치로 호출되면 "1"을, -xyz=abc로 호출되면 "abc"를 출력해요:
#!/usr/bin/perl -s
if ($xyz) { print "$xyz\n" }
--help 같은 스위치는 use strict "refs"에 부합하지 않는 ${-help} 변수를 만든다는 점에 유의하세요. 또 경고가 켜진 스크립트에서 이 옵션을 쓰면 "used only once" 경고가 많이 나올 수 있어요. 이런 이유로 -s 사용은 권장되지 않아요. 훨씬 유연한 스위치 파싱은 Getopt::Long을 보세요.
-S
프로그램 이름에 경로 구분자가 없으면 Perl이 PATH 환경 변수로 프로그램을 검색하게 해요. 일부 플랫폼에선 검색하며 파일 이름에 접미사도 붙여요. 예를 들어 Win32 플랫폼에선 원래 이름 조회가 실패하고 이름이 그 접미사 중 하나로 끝나지 않으면 .bat·.cmd 접미사를 붙여요. DEBUGGING을 켜고 컴파일했으면 -Dp 스위치로 검색 진행을 볼 수 있어요. 보통 #!를 지원하지 않는 플랫폼에서 #! 시작을 흉내 내는 데 써요. #!를 쓰고 셸의 $PATH 검색 메커니즘으로 보통 찾는 스크립트를 디버깅할 때도 편리해요. Bourne 셸과 호환되는 셸이 있는 많은 플랫폼에서 이 예시가 동작해요:
#!/usr/bin/perl
eval 'exec /usr/bin/perl -wS $0 ${1+"$@"}'
if 0; # ^ 셸 아래에서만 실행
시스템이 첫 줄을 무시하고 프로그램을 /bin/sh에 먹여, 셸이 Perl 프로그램을 셸 스크립트로 실행하려 시도해요. 셸이 둘째 줄을 일반 셸 명령으로 실행하며 Perl 인터프리터를 시작해요. 어떤 시스템에선 $0가 항상 전체 경로를 담지 않으므로, -S가 필요하면 프로그램을 검색하라고 Perl에 알려줘요. Perl이 프로그램을 찾으면 줄들을 파싱하고 if 0 검사가 절대 참이 아니라서 무시해요. 프로그램을 csh로 해석하려면 ${1+"$@"}를 $*로 바꿔야 하는데, 그건 인자 리스트의 내장 공백 등을 이해하지 못해요. csh가 아니라 sh를 시작하려면 어떤 시스템에선 #! 줄을 콜론 하나만 있는 줄로 바꿔야 할 수도 있는데, Perl이 정중히 무시해요. 다른 시스템은 그걸 제어할 수 없어서 csh·sh·Perl 어느 것 아래에서도 동작하는 완전히 사악한 구조가 필요해요:
eval '(exit $?0)' && eval 'exec perl -wS $0 ${1+"$@"}'
& eval 'exec /usr/bin/perl -wS $0 $argv:q'
if 0; # ^ 셸 아래에서만 실행
제공된 파일 이름에 디렉터리 구분자가 있고(그래서 절대·상대 경로이고) 그 파일이 안 보이면, 파일 확장자를 붙이는 플랫폼이 그걸 붙여 하나씩 찾아봐요. DOS류 플랫폼에선 프로그램에 디렉터리 구분자가 없으면 PATH보다 먼저 현재 디렉터리에서 검색해요. Unix 플랫폼에선 PATH에서만 엄격히 검색돼요.
-t
-T처럼 동작하지만 탠트 검사가 치명적 에러 대신 경고를 내요. 이 경고는 이제 no warnings qw(taint)로 평소처럼 제어할 수 있어요. 참고: 이것은 -T의 대체재가 아니에요! 오래된 코드를 보호하면서 임시 개발 보조로만 쓰도록 설계됐어요. 진짜 프로덕션 코드와 새로 작성하는 보안 코드엔 항상 진짜 -T를 써요. 탠트 지원 없이 빌드한 perl이면 효과가 없어요.
-T
"taint"를 켜서 테스트할 수 있게 해요. 보통 이 검사는 setuid·setgid로 돌 때만 해요. 꼭 신뢰할 수 없는 누군가를 대신해 도는 프로그램(CGI 프로그램이나 Perl로 쓴 인터넷 서버 같은)에선 명시적으로 켜는 게 좋아요. 자세한 건 perlsec을 보세요. 보안상 이 옵션은 Perl이 아주 일찍 봐야 해요. 보통 명령행 일찍 나타나거나, 그 구조를 지원하는 시스템에선 #! 줄에 있어야 해요.
-u
이 스위치는 Perl이 프로그램을 컴파일한 뒤 코어를 덤프하게 해요. 이론상 이 코어 덤프를 undump 프로그램(제공 안 됨)으로 실행 가능 파일로 바꿀 수 있어요. 이건 디스크 공간을 희생해 시작을 빠르게 해요 (실행 파일을 strip하면 최소화). 덤프 전에 프로그램 일부를 실행하고 싶으면 CORE::dump() 함수를 대신 써요. 참고: undump 가용성은 플랫폼별이고 특정 Perl 포트엔 없을 수 있어요.
-U
Perl이 안전하지 않은 연산을 허용하게 해요. 현재 유일한 "불안전한" 연산은 슈퍼유저로 디렉터리를 unlink하려는 것과, 치명적 탠트 검사가 경고로 바뀐 setuid 프로그램을 실행하는 거예요. 탠트 검사 경고를 실제 생성하려면 이 옵션과 함께 경고도 켜야 해요.
-v
perl 실행 파일의 버전·패치레벨을 출력해요.
-V
주요 perl 구성 값과 @INC의 현재 값을 출력해요.
-V:configvar
이름 붙은 구성 변수(들)의 값을 STDOUT으로 출력하는데, configvar 인자가 정규식처럼 보이면(문자 아닌 것이 있으면) 여러 개를 출력해요. 예:
$ perl -V:libc
libc='/lib/libc-2.2.4.so';
$ perl -V:lib.
libs='-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc';
libc='/lib/libc-2.2.4.so';
$ perl -V:lib.*
libpth='/usr/local/lib /lib /usr/lib';
libs='-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc';
lib_ext='.a';
libc='/lib/libc-2.2.4.so';
libperl='libperl.a';
....
추가적으로 콜론으로 형식 제어도 가능해요. 뒤따르는 콜론은 줄바꿈과 종결자 ;를 억제해 셸 명령에 쿼리를 내장할 수 있게 해요. (연상: PATH 구분자 :.)
$ echo "compression-vars: " `perl -V:z.*: ` " are here !"
compression-vars: zcat='' zip='zip' are here !
앞서는 콜론은 응답에서 "name=" 부분을 제거해 필요한 이름에 매핑하게 해줘요. (연상: 빈 라벨)
$ echo "goodvfork="`./perl -Ilib -V::usevfork`
goodvfork=false;
앞·뒤 콜론을 함께 써서 이름 없이 위치 파라미터 값을 얻을 수도 있어요. 아래 경우 PERL_API 파라미터가 알파벳순으로 반환된다는 걸 주목하세요.
$ echo building_on `perl -V::osname: -V::PERL_API_.*:` now
building_on 'linux' '5' '1' '9' now
-w
한 번만 언급된 변수 이름, 설정 전에 쓰인 스칼라 변수, 재정의된 서브루틴, 정의되지 않은 파일핸들에 대한 참조, 읽기 전용으로 열었는데 쓰려는 파일핸들, 숫자처럼 보이지 않는데 숫자로 쓰이는 값, 배열을 스칼라처럼 쓰는 것, 서브루틴이 100단계 이상 재귀하는 것, 그 외 수많은 것 등 모호한 구조에 대한 경고를 출력해요.
이 스위치는 사실 전역 $^W 변수만 켜요. 보통은 어휘 스코프된 use warnings 프래그마가 선호돼요. 특정 경고를 끄거나 치명적 에러로 승격하려면 perlvar와 perlfunc의 "warn"에 설명된 __WARN__ 훅을 써요. perldiag와 perltrap도 보세요. 경고 클래스 전체를 조작하고 싶으면 세밀한 경고 기능인 warnings도 이용 가능해요.
-W
no warnings나 $^W에 상관없이 모든 경고를 켜요. warnings를 보세요.
-X
use warnings나 $^W에 상관없이 모든 경고를 꺼요. warnings를 보세요. "PERL5OPT"에선 금지돼요.
-x, -xdirectory
Perl에게 프로그램이 메일 메시지 같은 더 큰 무관한 텍스트에 내장돼 있다고 알려줘요. #!로 시작하고 "perl" 문자열을 포함한 첫 줄까지 앞의 가비지를 버려요. 그 줄의 의미 있는 스위치는 적용돼요.
프로그램이 하는 모든 줄 번호 참조(경고·에러...)는 #! 줄을 첫 줄로 취급해요. 그래서 프로그램 2번째 줄(파일의 100번째 줄)의 경고는 100이 아니라 2번째 줄로 보고돼요. #line 지시문으로 덮어쓸 수 있어요. (perlsyn의 "Plain Old Comments (Not!)" 참고.)
디렉터리 이름이 지정되면 Perl은 프로그램 실행 전에 그 디렉터리로 전환해요. -x 스위치는 앞의 가비지 폐기를 제어할 뿐이에요. 무시할 뒤의 가비지가 있으면 프로그램은 __END__로 끝나야 해요. 프로그램은 원하면 DATA 파일핸들로 뒤의 가비지의 일부·전부를 처리할 수 있어요. 디렉터리는 -x 직후에 공백 없이 와야 해요.
환경 (ENVIRONMENT)
- HOME: chdir에 인자가 없을 때 사용.
- LOGDIR: chdir에 인자 없고 "HOME"이 설정 안 됐을 때 사용.
- PATH: 서브프로세스 실행과,
-S를 쓸 때 프로그램 찾기에 사용. - PERL5LIB: 표준 라이브러리보다 먼저 Perl 라이브러리 파일을 찾을 디렉터리 리스트. 지정 위치 아래의 version/archname/, version/, archname/ 같은 아키텍처·버전 특정 디렉터리는 존재하면 자동 포함되고, 이 조회는 인터프리터 시작 시 이뤄져요. 또한
$Config{inc_version_list}항목과 일치하는 디렉터리도 추가돼요. PERL5LIB가 정의 안 되면 "PERLLIB"를 써요. 디렉터리는 유닉스류에선 콜론, Windows에선 세미콜론으로 구분돼요 (정확한 경로 구분자는perl -V:path_sep). 프로그램이 setuid·setgid였거나-T·-t스위치를 지정해서 탠트 검사를 돌 때는 PERL5LIB·PERLLIB 둘 다 참조되지 않아요. 대신 프로그램이use lib "/my/directory";라고 해야 해요. - PERL5OPT: 명령행 옵션(스위치). 이 변수의 스위치는 모든 Perl 명령행에 있는 것처럼 취급돼요.
-[CDIMTUWdmtw]스위치만 허용돼요. 탠트 검사 시엔 무시돼요. PERL5OPT가-T로 시작하면 탠팅이 활성화되고 이후 옵션이 무시돼요.-t로 시작하면 탠팅이 활성화되고, 쓰기 가능한 dot가@INC에서 제거되며, 이후 옵션이 존중돼요. - PERLIO: 공백(또는 콜론) 구분된 PerlIO 레이어 리스트. perl이 PerlIO 시스템으로 IO를 쓰도록 빌드됐으면(기본) 이 레이어들이 Perl의 IO에 영향. 레이어 이름 앞에 콜론(
:perlio처럼)을 붙이는 게 관례지만, 레이어 지정 문자열을 파싱하는 코드(PERLIO 환경 변수 디코딩에도 쓰임)는 콜론을 구분자로 취급해요. 설정 안 됨·빈 PERLIO는 플랫폼의 기본 레이어 셋과 동등해요. 예: 유닉스류에선:unix:perlio, Windows·DOS류에선:unix:crlf. 이 리스트는 Perl의 모든 IO의 기본이 돼요. 그래서 내장 레이어만 나타날 수 있어요. 외부 레이어(:encoding()같은)는 로드에 IO가 필요하니까요! 외부 인코딩을 기본으로 추가하려면 "open pragma"를 보세요. PERLIO에 넣을 만한 레이어 요약:- :crlf: MS-DOS와 비슷한 방식으로 "텍스트"·"이진" 파일을 구분하며 CRLF를 "\n"으로 번역하고, 그 아키텍처에선 :perlio와 비슷한 버퍼링도 제공하는 레이어.
- :perlio: PerlIO 레이어로 작성된 stdio류 버퍼링의 재구현. 아래 레이어(보통 :unix)를 호출해 동작해요.
- :stdio: 시스템의 ANSI C "stdio" 라이브러리 호출을 감싸 PerlIO 인터페이스를 제공하는 레이어. 버퍼링과 IO 둘 다 제공. :stdio 레이어는 플랫폼의 정상 동작이어도 CRLF 번역을 하지 않아요. 그 위에 :crlf 레이어가 필요해요.
- :unix: read, write, lseek 등을 호출하는 저수준 레이어.
기본 레이어 셋은 모든 플랫폼에서 수용 가능한 결과를 줘야 해요. 유닉스 플랫폼에선
:unix:perlio또는:stdio와 동등해요. 시스템 라이브러리가 버퍼에 빠른 접근을 제공하면 Configure가:stdio구현을 선호하고(현대 아키텍처에선 흔치 않음), 아니면:unix:perlio를 써요. Win32에서 이 릴리스(5.30)의 기본은:unix:crlf예요. Win32의:stdio는 C 컴파일러 버전·벤더에 좀 의존하는 여러 버그·미기능이 있어요. 우리 :crlf 레이어를 버퍼로 쓰면 그 문제를 피하고 더 균일해져요. 이 릴리스는 Win32에서 :unix를 최하위 레이어로 쓰므로 여전히 C 컴파일러의 숫자 파일 디스크립터 루틴을 써요. PERLIO 환경 변수는 perl이 탠트 모드로 돌 때 완전히 무시돼요.
- PERLIO_DEBUG:
-Di명령행 스위치로 Perl을 돌 때 파일·장치 이름으로 설정하면, PerlIO 하위시스템의 특정 연산 로깅이 기본인 stderr 대신 지정 파일로 가요. 파일은 append 모드로 열려요. 일반적 사용:
% env PERLIO_DEBUG=/tmp/perlio.log perl -Di script ...
Win32에선 대략적으로:
> set PERLIO_DEBUG=CON
perl -Di script ...
이 기능은 setuid 스크립트, -T로 도는 스크립트, -DDEBUGGING 지원 없이 빌드된 Perl에서 도는 스크립트에선 비활성화돼요.
- PERLLIB: 표준 라이브러리보다 먼저 찾을 디렉터리 리스트. "PERL5LIB"가 정의되면 PERLLIB는 안 써요. 탠트 모드에선 완전히 무시돼요.
- PERL5DB: 디버거 코드를 로드하는 명령. 기본은:
BEGIN { require "perl5db.pl" }
PERL5DB는 Perl이 그냥 -d 스위치로 시작될 때만 사용돼요.
- PERL5DB_THREADED: 참 값으로 설정하면 디버거에게 디버깅 중인 코드가 스레드를 쓴다고 알려줘요.
- PERL5SHELL (Win32 포트 전용): Win32에서만, Perl이 "백틱" 명령이나 system()을 실행할 때 내부적으로 써야 하는 대체 셸로 설정할 수 있어요. 기본은 WindowsNT에선 cmd.exe /x/d/c, Windows95에선 command.com /c. 값은 공백 구분으로 간주돼요. 공백·백슬래시처럼 보호해야 할 문자는 앞에 백슬래시를 붙여요. Perl은 COMSPEC을 이 용도로 쓰지 않아요. COMSPEC가 사용자마다 변동이 커 이식성 문제가 있기 때문이에요. 게다가 Perl은 대화형 사용에 안 맞는 셸도 쓸 수 있는데, COMSPEC를 그런 셸로 설정하면 다른 프로그램의 정상 동작을 방해할 수 있어요. Perl 5.10.0·5.8.8 이전엔 PERL5SHELL이 외부 명령 실행 때 탠트 검사되지 않았어요. Windows에서 탠트 모드로 돌 땐
$ENV{PERL5SHELL}을 명시적으로 설정(또는 삭제)하는 게 좋아요. - PERL_ALLOW_NON_IFS_LSP (Win32 전용): non-IFS 호환 LSP(레이어드 서비스 제공자) 사용을 허용하려고 1로 설정. Perl은 보통 Windows 소켓을 진짜 파일핸들로 에뮬레이션하려면 IFS 호환 LSP가 필요해서 그걸 찾아요. 하지만 McAfee Guardian 같은 방화벽이 모든 앱에 자기 LSP를 요구하면서 IFS 호환이 아니면 문제가 될 수 있어요. 이걸 1로 설정하면 Perl이 카탈로그에서 열거된 첫 적합한 LSP를 쓰고, McAfee Guardian도 만족하고 Perl도 동작해요.
- PERL_DEBUG_MSTATS: Perl 배포판 포함 malloc로 Perl을 컴파일했을 때만 관련(
perl -V:d_mymalloc이 "define"이면). 설정하면 실행 후 메모리 통계를 덤프하고, 1보다 큰 정수로 설정하면 컴파일 후에도 덤프해요. - PERL_DESTRUCT_LEVEL: 객체·다른 리퍼런스의 전역 소멸 동작을 제어. 자세한 건 perlhacktips의 "PERL_DESTRUCT_LEVEL" 참고.
- PERL_DL_NONLAZY: 동적 라이브러리를 로드할 때 모든 미정의 심볼을 해석하도록 "1"로 설정. 기본 동작은 쓰일 때 심볼을 해석하는 것. 확장 테스트 중 유용한데, 테스트 스위트가 호출하지 않아도 오타 난 함수 이름에 에러를 받게 해줘요.
- PERL_ENCODING: 명시적 인코딩 이름 없이
use encoding프래그마를 쓰면 PERL_ENCODING에서 인코딩 이름을 찾아요. - PERL_HASH_SEED: (Perl 5.8.1부터, 5.18.0에 새 의미) Perl 내부 해시 함수의 랜덤화를 덮어쓰는 데 사용. 값은 16진수로 표현되고 앞 0x가 올 수 있어요. 잘린 패턴은 필요한 만큼 0이 붙은 것처럼 취급돼요. 옵션이 주어지고 PERL_PERTURB_KEYS가 설정 안 됐다면, '0' 값은 PERL_PERTURB_KEYS=0/NO를, 다른 값은 PERL_PERTURB_KEYS=2/DETERMINISTIC을 뜻해요. DETERMINISTIC 모드의 중요 주의사항은 PERL_PERTURB_KEYS 문서를 보세요. 주의: 해시 시드는 민감 정보예요. 해시는 Perl 코드에 대한 로컬·원격 공격을 막으려고 랜덤화돼요. 시드를 수동 설정하면 이 보호가 일부·전부 사라질 수 있어요. 자세한 건 perlsec의 "Algorithmic Complexity Attacks", "PERL_PERTURB_KEYS", "PERL_HASH_SEED_DEBUG"를 보세요.
- PERL_PERTURB_KEYS: (5.18.0부터) "0"/"NO"로 설정하면 키 순회가 같은 PERL_HASH_SEED에 대해 실행마다 반복 가능해요. 해시 삽입은 (공간만 더 제공하는 것 외엔) 순서를 바꾸지 않아요. PERL_HASH_SEED 설정과 결합하면 5.18 이전 동작에 최대한 가까워져요. "1"/"RANDOM"으로 설정하면 키 순회가 랜덤화돼요. 해시에 삽입할 때마다 키 순서가 랜덤으로 바뀌어요. PERL_HASH_SEED를 지정해도 다음 실행에서 반복 가능하지 않을 수 있어요. PERL_HASH_SEED가 명시 제공되지 않을 때의 기본 모드예요. "2"/"DETERMINISTIC"으로 설정하면 해시에 키 삽입 시 키 순서가 바뀌지만, 같은 해시 시드를 쓰고 코드가 스스로 비결정적 연산을 안 하며 정확히 같은 환경 문맥이면 실행마다 반복 가능해요. 환경 변수 추가·제거는 키 순서를 바꿀 가능성이 커요. 코드 일부가 비결정적 키(리퍼런스의 문자열화 형태나 포함 객체의 주소로 키 잡는 등)로 해시를 만들면 프로세스의 모든 해시 키 순서에 전역 영향이 있을 수 있어요. 제대로 동작하려면 결정적 결과를 위해 PERL_HASH_SEED와 짝을 이뤄야 하고, 사실 PERL_HASH_SEED를 명시 설정하면 이것도 자동으로 이 모드로 설정돼요. 참고: 이 옵션 사용은 불안전한 것으로 간주되며, Perl 해시 함수의 비결정적 동작 디버깅 전용이에요. 프로덕션에서 쓰지 마세요. 자세한 건 perlsec의 "Algorithmic Complexity Attacks"와 "PERL_HASH_SEED"·"PERL_HASH_SEED_DEBUG"를 보세요. 특정 해시의 키 순회 마스크는 Hash::Util의
hash_traversal_mask()함수로 얻고 설정할 수 있어요. - PERL_HASH_SEED_DEBUG: (5.8.1부터) "1"로 설정하면 실행 시작 시 해시 함수·시드·적용 중인 키 순회 랜덤화 종류에 대한 정보를 (STDERR로) 표시해요. 해시 함수 정보, 특히 해시 시드는 민감 정보예요. 알면 Perl 코드에 원격으로도 DoS 공격을 꾸밀 수 있어요. 알 필요 없는 사람에게 해시 시드를 공개하지 마세요. 예시 출력:
HASH_FUNCTION = ONE_AT_A_TIME_HARD HASH_SEED = 0x652e9b9349a7a032 PERTURB_KEYS = 1 (RANDOM)
- PERL_MEM_LOG:
-Accflags=-DPERL_MEM_LOG로 설정했다면 PERL_MEM_LOG 환경 변수가 디버그 메시지 로깅을 켜요. 값은<number>[m][s][t]형태. number는 쓸 파일 디스크립터 번호(기본 2), 글자 조합은 (m)emory·(s)v 정보를 (t)imestamp와 함께 원하는지 지정. 예:PERL_MEM_LOG=1mst. 다른 열린 fd에 여러 방법으로 쓸 수 있어요:
$ 3>foo3 PERL_MEM_LOG=3m perl ...
- PERL_ROOT (VMS 전용): VMS에서만 Perl과 @INC 경로의 논리 장치를 포함하는 변환 숨김 루트 논리 이름. VMS에서 Perl에 영향 주는 다른 논리 이름엔 PERLSHR, PERL_ENV_TABLES, SYS$TIMEZONE_DIFFERENTIAL이 있고, 선택 사항이며 perlvms와 소스 배포판 README.vms에서 다뤄져요.
- PERL_SIGNALS: 5.8.1 이상에서 사용 가능. "unsafe"로 설정하면 Perl 5.8.0 이전의 (즉각적이지만 불안전한) 신호 동작이 복원돼요. "safe"로 설정하면 안전한(그러나 지연된) 신호가 쓰여요. perlipc의 "Deferred Signals (Safe Signals)" 참고.
- PERL_UNICODE:
-C명령행 스위치와 동등. 불리언 변수가 아니라는 점을 주의하세요. "1"로 설정하는 건 "유니코드 켜기"의 올바른 방법이 아니에요. "0"으로 "유니코드 끄기"는 할 수 있어요.-C스위치 설명을 보세요. - PERL_USE_UNSAFE_INC: 현재 디렉터리를 기본 @INC에 두지 않도록 perl이 설정됐으면, 이 변수를 "1"로 설정해 복원할 수 있어요. 주로 "."이 @INC에 없다는 것을 처리하도록 갱신 안 된 모듈을 빌드·테스트할 때 쓰려는 것이고, 일상 사용 환경엔 설정하면 안 돼요.
- SYS$LOGIN (VMS 전용): chdir에 인자 없고 "HOME"·"LOGDIR"이 설정 안 됐을 때 사용.
- PERL_INTERNAL_RAND_SEED: 다양한 용도로 perl이 내부적으로 쓰는 난수 생성기를 초기화하려고 음이 아닌 정수로 설정. perl이 setuid·setgid로 돌면 무시돼요.
-T·-t로 탠팅 켜고 시작하면 일부 제한된 시작 랜덤화(해시 키)에만 사용. perl은 이 변수를 무시하도록 빌드될 수 있어요. - PERL_RAND_SEED: 정수 값으로 설정하면, 명시적 srand() 호출 없이 rand()를 쓸 때나 명시적 무인자 srand() 호출 시 perl 내부 난수 생성기를 초기화하는 데 이 값이 쓰여요. 보통 srand() 전에 rand()를 부르거나 무인자 srand()를 명시 호출하면 생성기가 비교적 고품질 랜덤 시드로 "최선"을 다해 초기화돼요. 이 변수가 설정되면 시드가 환경 변수 값에서 결정적으로 계산돼, 앱 프로세스와 포크·스레드가 각자 고유 시드를 가지되 rand() 기준으론 프로그램을 두 번 돌려도 동일한 결과가 나올 수 있어요. PERL_RAND_SEED는 성능 측정·디버깅용이고 안정적 테스트용이 아님을 명시적으로 의도해요. 유일한 보장은 특정 perl 실행 파일이 두 번 연속 같은 결과를 낸다는 것뿐이고, 릴리스 간·아키텍처 간 결과가 같다는 보장은 없어요. setuid·setgid로 돌면 무시돼요.
Perl에는 특정 자연 언어의 데이터를 어떻게 처리할지 제어하는 환경 변수도 있고, 그건 perllocale을 보세요. Perl과 그 모듈·구성요소(테스트 프레임워크 포함)는 때로 다른 환경 변수를 쓰기도 해요. 일부는 특정 플랫폼 특이예요. 적절한 모듈 문서와 플랫폼 문서(perlsolaris, perllinux, perlmacosx, perlwin32 등)를 확인하세요.
Perl은 모든 환경 변수를 실행 중인 프로그램에 제공하고, 시작하는 자식 프로세스에도 넘겨줘요. 하지만 setuid로 도는 프로그램은 다른 어떤 것보다 먼저 다음 줄들을 실행해 사람들을 정직하게 만드는 게 좋아요:
$ENV{PATH} = "/bin:/usr/bin"; # or whatever you need
$ENV{SHELL} = "/bin/sh" if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
적용 순서 (ORDER OF APPLICATION)
일부 옵션, 특히 -I, -M, PERL5LIB, PERL5OPT는 상호작용할 수 있고, 적용 순서가 중요해요. 이 절은 perl 인터프리터 내부에서 실제로 일어나는 일이 아니라 효과적으로 일어나는 일을 문서화해요.
-I
여러 -I 옵션의 효과는 오른쪽에서 왼쪽으로 @INC 앞에 unshift하는 거예요:
perl -I 1 -I 2 -I 3
먼저 @INC 앞에 3을, 그다음 2, 그다음 1을 붙여요. 결과는 @INC가 qw(1 2 3)으로 시작해요.
-M
여러 -M 옵션은 왼쪽에서 오른쪽으로 처리돼요:
perl -Mlib=1 -Mlib=2 -Mlib=3
먼저 lib 프래그마로 1을 @INC 앞에 붙이고, 2, 3을 붙여 @INC가 qw(3 2 1)로 시작해요.
PERL5LIB 환경 변수
콜론 구분 디렉터리 리스트를 담아요. 전체 리스트가 한 번에 @INC 앞에 붙어요:
PERL5LIB=1:2:3 perl
@INC가 qw(1 2 3)으로 시작해요.
-I, -M, PERL5LIB 조합
PERL5LIB가 먼저 적용되고, 그다음 모든 -I 인자, 그다음 모든 -M 인자:
PERL5LIB=e1:e2 perl -I i1 -Mlib=m1 -I i2 -Mlib=m2
@INC가 qw(m2 m1 i1 i2 e1 e2)로 시작해요.
PERL5OPT 환경 변수
공백 구분 스위치 리스트를 담아요. 여기선 -M과 -I의 효과만 고려해요. 명령행의 -I 스위치 정상 처리 후, PERL5OPT의 모든 -I 스위치가 추출돼요. 오른쪽→왼쪽 대신 왼쪽→오른쪽으로 처리돼요. 명령행에선 -I와 디렉터리 사이 공백이 허용되지만 PERL5OPT에선 안 된다는 점도 주의하세요. 명령행 -M 스위치 정상 처리 후 PERL5OPT의 모든 -M 스위치가 추출돼요. 명령행과 마찬가지로 왼쪽→오른쪽 처리돼요. 예시:
export PERL5OPT="-Mlib=optm1 -Iopti1 -Mlib=optm2 -Iopti2"
export PERL5LIB=e1:e2
perl -I i1 -Mlib=m1 -I i2 -Mlib=m2
@INC가 이렇게 시작해요:
qw(
optm2
optm1
m2
m1
opti2
opti1
i1
i2
e1
e2
)
기타 복잡성
위 예시에서 무시된 몇 가지 복잡성이 있어요:
- arch·version 하위 디렉터리: -I, PERL5LIB, use lib 모두 존재하면 arch·version 하위 디렉터리도 붙여요.
- sitecustomize.pl: 시작 시 실행될 수 있어요 (위 -f 참고).