40 번째 수정본 소스 보기 : Perl/파일
마지막으로 [b]
-- Loading page list... --
내용출력
로그인[l]
Diary
[f]
최근변경내역
[r]
페이지목록[i]
횡설수설[2]
게시판[3]
링크
수정할 수 없습니다: Perl/파일 는 읽기 전용 페이지입니다.
== # 기본적인 입출력 == * open FILEHANDLE, MODE, EXPR ** EXPR 은 주로 파일명 ** MODE ***
<
또는 없음 : 읽기모드 ***
>
: 쓰기모드. 파일이 존재할 경우 내용을 지움 ***
>>
: 추가모드. 파일이 존재할 경우 마지막에 내용을 추가함 ***
+<
: 읽기, 쓰기 ***
+>
: 읽기, 쓰기. 파일이 존재할 경우 내용을 지움 ***
+>>
: 읽기, 추가하기 ***
|-
: 출력 파이프 ***
-|
: 입력 파이프 ** open에 실패하면 $! 변수에 에러 내용이 담긴다. * 읽거나 쓰고 ** @allLine =
; 파일 전부를 읽기 ** $aLine =
; 한 줄 읽기 ** print fileHandle "안녕"; 출력 * close( fileHandle ); 로 닫는다. 한 줄씩 읽는 예제: {{{#!vim perl open my $fileHandle, "<", $fileName ) or die "Cannot open $fileName: $!"; while( $aLine = <$fileHandle> ) { print $aLine; } close $fileHandle; # 변수를 생략하면 $_ 사용 while (<$fileHandle>) { # (defined ($_ = <$fileHandle>)) print "$_"; } }}} 배열 변수를 써서 통채로 읽는 예제: (파일이 크면 메모리를 많이 소모할 수 있으므로 주의) {{{#!vim perl open my $fileHandle, "<", $fileName or die "Cannot open $fileName: $!"; @allLines = <$fileHandle>; close $fileHandle; }}} "input record separator" 변수 $/의 값을 바꿈으로써 스칼라 변수에 파일 전체를 담는 경우. ($/의 기본값은 "\n") {{{#!vim perl local $/ = undef; open my $fileHandle, "<", $fileName or die "Cannot open $fileName: $!"; $allLines = <$fileHandle>; close $fileHandle; }}} 파일을 통채로 읽거나 쓰는 것은 Cpan:File::Slurp 모듈을 쓰면 편하다. === # 읽기쓰기 모드에서 읽기와 쓰기의 전환 === "+<", "+>", "+>>" 를 사용하여 열 경우에, 읽는 동작과 쓰는 동작을 번갈아가며 수행할 경우 예상치 않은 결과가 나올 수 있다([http://cafe.naver.com/perlstudy/1244 예]) 읽기와 쓰기 동작 사이에는
seek
를 써서 제대로 파일포지션 포인터를 세팅해 주어야 하는 듯. === # chomp === 스트링 뒤의 new line "\n"을 제거
정확히는, $/변수의 값을 제거
{{{#!vim perl $line =
; chomp $line; # 한 줄로 chomp ($line =
); ## 리스트의 경우는, 각 엘리먼트의 "\n"을 일괄 제거 chomp (@lines =
); }}} === # 인자 3개 형태의 open을 쓰자 === 파일명에 잘못된 문자(부등호 등)가 포함되거나, 악의적으로 파이프 등을 사용하는 것에 대비해서, 인자 3개 형태로 사용하자. {{{#!vim perl open FH, $filename; # 이건 위험 open FH, "< $filename"; # 입력의 경우 "<"가 없어도 되지만 명시하는게 안전 # perl 5.6 이상부터는 별개의 인자로 줄 수 있음 open FH, "<", $filename; # 이것을 권장 }}} === # 파일핸들도 렉시컬 변수를 쓸 수 있다 === {{{#!vim perl open FH, "<", $filename; # FH 는 전역적인 파일핸들 open my $fh, "<", $filename; # $fh 는 렉시컬 변수. 권장 }}} == # <ARGV> ==
또는 <> - 명령행 인자로 들어온 스트링을 파일명으로 취급하여 모든 파일들을 열고 읽음. 인자가 없으면 표준입력을 읽음. 현재 읽고 있는 파일의 이름은 $ARGV 에 담긴다. {{{#!vim perl #!/usr/bin/perl # nl3.plx use warnings; use strict; my $lineno; my $current = ""; while (<>) { if ($current ne $ARGV) { $current = $ARGV; print "\n\t\tFile: $ARGV\n\n"; $lineno=1; } print $lineno++; print ": $_"; } }}} == # $/ == * $/ = ""; - blank line을 구분자로 함 (단락 단위로 읽는다고 볼 수 있다) * $/ = undef; - file 내용 전체를 하나의 스칼라로 읽음 * $/ = \1024; (양수의 레퍼런스) - 한 번에 1024바이트를 읽음
* chomp 의 역할은 인자의 제일 뒤에 $/ 변수의 값이 있는 경우 그것을 제거
== # 파일 핸들끼리의 할당 == {{{#!vim perl if (defined $input) { open INPUT, $input or die "Couldn't open file $input: $!\n"; } else { *INPUT = *STDIN; # typeglob을 사용해야 함 } }}} === # 파일 핸들을 서브루틴의 인자로 넘기기 === {{{#!vim perl # typeglob 사용 sub say_hello { *WHERE = shift; print WHERE "Hi there!\n"; } say_hello(*STDOUT); ## 또는 sub say_hello { my $fh = shift; # 일반 변수에 print $fh "Hi there!\n"; } say_hello(*STDOUT); # 호출하는 쪽에서는 typeglob }}} == # 바이너리 파일 입출력 == {{{#!vim perl binmode FILEHANDLE; }}} == # select ==
write
나
print
등 출력에 사용되는 디폴트 파일 핸들을 지정하며, 현재의 디폴트 파일 핸들을 반환한다. {{{#!vim perl select LOG; print "blah blah...\n"; # LOG에 해당하는 파일로 출력된다. select STDOUT; # 표준출력으로 복원 }}} == # 버퍼링 == select 로 지정된 파일핸들에 대하여 * $| = 0; - 운영체제의 버퍼링 사용 (기본값) * $| = 1; - 버퍼링 사용하지 않음 {{{#!vim perl $| = 1; for (1...20) { print "."; # 버퍼링이 사용될 경우, 20초 후에 한꺼번에 20개의 "."이 출력된다. sleep 1; } print "\n"; }}} [http://perl.plover.com/FAQs/Buffering.html Suffering from Buffering?] 글도 참고 == # 디렉토리 == === # chdir === chdir - working directory 변경
* 변경된 디렉토리는 자식 프로세스에 상속됨 * 파라메터가 생략되었을 경우는 '''$_을 쓰는 게 아니라''' 현재 사용자의 홈 디렉토리로 변경 시도 * 쉘의 cd에서 가능한 ~username 형식은 지원하지 않는다. - 이것은 OS가 아니라 쉘의 기능 === # Globbing === Globbing - 파일명 패턴 확장
{{{#!vim perl my @all_files = glob "*"; my @pm_files = glob "*.pm"; my @all_files_including_dot = glob ".* *"; # 패턴들은 공백으로 구분 # 또는 my @all_files = <*>; }}} === # Directory Handle === opendir로 열고, readdir로 읽고, closedir로 닫는다
* readdir의 리턴값은 경로명을 제외한 파일명만 들어 있으니 주의 {{{#!vim perl opendir DH, "." or die "Couldn't open the current directory: $!"; while ($_ = readdir(DH)) { # readdir은 파일명을 하나씩 반환 next if $_ eq "." or $_ eq ".."; print $_, " " x (30-length($_)); print "d" if -d $_; print "r" if -r _; # "_"는 "마지막으로 테스트한 파일"을 의미 # ... } closedir DH; } }}} == # 파일 관련 테스트 연산자 == 파일 속성 테스트 연산자들
|< File test |< Meaning || |< -r |< File or directory is readable by this (effective) user or group || |< -w |< File or directory is writable by this (effective) user or group || |< -x |< File or directory is executable by this (effective) user or group || |< -o |< File or directory is owned by this (effective) user || |< -R |< File or directory is readable by this real user or group || |< -W |< File or directory is writable by this real user or group || |< -X |< File or directory is executable by this real user or group || |< -O |< File or directory is owned by this real user || |< -e |< File or directory name exists || |< -z |< File exists and has zero size (always false for directories) || |< -s |< File or directory exists and has nonzero size (the value is the size in bytes) || |< -f |< Entry is a plain file || |< -d |< Entry is a directory || |< -l |< Entry is a symbolic link || |< -S |< Entry is a socket || |< -p |< Entry is a named pipe (a "fifo") || |< -b |< Entry is a block-special file (like a mountable disk) || |< -c |< Entry is a character-special file (like an I/O device) || |< -u |< File or directory is setuid || |< -g |< File or directory is setgid || |< -k |< File or directory has the sticky bit set || |< -t |< The filehandle is a TTY (as reported by the isatty( ) system function; filenames can't be tested by this test) || |< -T |< File looks like a "text" file || |< -B |< File looks like a "binary" file || |< -M |< Modification age (measured in days) || |< -A |< Access age (measured in days) || |< -C |< Inode-modification age (measured in days) || == # stat, lstat == 심볼릭 링크의 경우 stat은 링크가 가리키는 파일에 대한 정보를 얻어온다. 링크 자체의 정보를 얻고 싶다면 lstat을 사용
{{{#!vim perl my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($filename); }}} == # special underscore filehandle == 동일한 파일에 여러 번 파일 테스트 연산자,stat,lstat 연산을 수행하는 경우, "_"를 인자로 주면 기존 연산 시 얻어온 정보를 재사용한다. (서브루틴 등에서 stat을 부르는 바람에 자신도 모르는 사이에 대상 파일이 바뀌었을지 모르니 주의)
{{{#!vim perl push @big_old_files, $_ if (-s) > 100_000 and -A _ > 90; # -A 의 인자로 "_" }}} 참고:
-l _
의 경우는 가장 최근에 파일 정보를 얻어온 방법이
lstat
이어야만 의미가 있다.
stat
은 심볼릭 링크의 경우 실제 타겟 파일을 찾아가서 정보를 얻어오므로 -l 연산의 결과가 결코 참이 되지 않기 때문이다. 직전에 수행한 게 lstat 이 아닐 경우 "The stat preceding -l _ wasn't an lstat"라는 에러가 난다.
== # 파일, 디렉토리 관련 명령어와 함수 == * rename OLDNAME, NEWNAME * unlink LIST {{{#!vim perl $cnt = unlink ’a’, ’b’, ’c’; unlink @goners; unlink <*.bak>; }}} * link OLDFILE, NEWFILE - 하드 링크 * symlink OLDFILE, NEWFILE - 심볼릭 링크 ** readlink EXPR - 심볼릭 링크의 값을 읽음 * mkdir FILENAME, MASK * rmdir FILENAME ** 빈 디렉토리만 삭제 가능 ** File::Path 모듈의 rmtree를 쓰면 편하다 * chmod LIST ** ex) chmod 0755, "fred", "barney"; * chown LIST ** ex) chown $user, $group, @filenames; ** user ID와 group ID는 숫자. 이름으로부터 얻고 싶다면 getpwnam, getgrnam 사용하여 해당 숫자 값을 먼저 얻을 것 * utime LIST - 액세스 시각과 수정 시각 변경 ** ex) utime $atime, $mtime, @filenames; == # 인코딩 지정 == 파일 입출력 Layer에서 인코딩/디코딩 변환을 지정할 수 있음
{{{#!vim perl # UTF-8로 저장된 파일을 읽어서 디코드 open my $fh, '<:utf8', 'file.txt'; # UTF-8로 저장된 파일을 읽어서 디코드 - 정합성 체크까지 open my $fh, '<:encoding(UTF-8)', 'file.txt'; # EUC-KR로 저장된 파일을 읽어서 디코드 open my $fh, '<:encoding(EUC-KR)', 'file.txt'; # UTF-8로 인코드하여 저장 open my $fh, '>:utf8', 'file.txt'; # 이미 열려 있는 파일 핸들은 binmode 로 지정 가능 binmode STDIN,':utf8'; }}} == # 스트링 변수를 파일처럼 읽거나 쓰기 == Perl 5.8 부터 지원 {{{#!vim perl my $string; open my $fh, ">", \ $string; # 위 두 줄을 아래처럼 쓸 수도 있음 open my $fh, ">", \ my $string; # 일반적으로 파일을 다루듯이 쓸 수 있음 print $fh "Hello"; }}} 단, 파일 핸들과 연결되어 있는 상태의 스트링 변수에 다른 형태로 접근할 경우 의도하지 않은 결과가 나오니 주의.
== # 기타 == * [http://perl.plover.com/FAQs/Buffering.html Suffering from Buffering?] == # Comments ==
---- [[컴퓨터분류]]
Perl/파일
페이지로 돌아가기 |
다른 수정본 보기