KTUGFaq

KTUG FAQ

로그인:
비밀번호:
가입
You will be imprisoned for contributing your time and skill to a bank robbery.
FrontPage › PerlTeX

LaTeX 매크로를 펄 코드로 작성할 수 있도록 해 주는 패키지.


목차

1 소개
2 사용법
3 보기1: 한글 Sorting 예제
4 보기2: DB와 연동한 List Plot 그리기
4.1 DB관련 사전 작업
4.2 DB에서 데이터 가져오기
4.3 perlTeX와 PSTricks를 이용하여 list plot graph 작성
4.4 결과 얻어 내기
5 질문
6 질문에 대한 저의 생각(오인수)

1 소개


Perl 코드를 가지고 LaTeX 매크로를 정의해 써먹는 재미있는 패키지이다. Perl 매크로가 LaTeX 매크로로 되는 것이다. 이로써 LaTeX의 조판 능력과 Perl의 프로그래밍 능력을 결합할 수 있게 된다.



2 사용법

프리앰블에 \usepackage{perltex}라고 선언한다. 이제 \perlnewcommand, \perlrenewcommand, \perlnewenvironment, \perlrenewenvironment의 네가지 명령을 이용할 수 있다.

문서컴파일은 perltex.pl이라는 스크립트를 사용한다. 옵션은 다음과 같다.
--latex=program
        기본값인 latex 대신 다른 실행명령(예:pdflatex)을 줄 수 있다.
--nosafe
        기본값으로 위험한 Perl코드(예: 파일삭제)가 실행되지 않도록 되어 있는데
        이 옵션은 안전장치를 풀어준다. 모든 Perl 코드가 그대로 실행된다.
--permit=feature
        특정 Perl코드만을 안전장치로부터 해제한다. 여러번 옵션을 줄 수 있다.

3 보기1: 한글 Sorting 예제

TeX으로는 문자열을 소팅하는 코드를 짜기가 쉽지않다. PerlTeX에게 이런 것은 식은 죽 먹기보다 쉽다.

test.tex:
\documentclass[a4paper]{article}
\usepackage{perltex}
\usepackage{dhhangul}
\perlnewcommand{\sortarg}[1]{join ',', sort split ',', $_[0]}
\newcommand{\teststring}{한글,가나다,우리나라,대한민국}
\begin{document}
\begin{center}
\teststring\\
$\Downarrow$\\
\sortarg{\teststring}
\end{center}
\end{document}
PerlTeXTeX 매크로를 만나면 이를 확장(expand)한 후 Perl로 처리한다. 확장을 못하게 하려면 \noexpandTeX 매크로 앞에 붙이면 된다.

컴파일:
$ perltex.pl --latex=lambda --nosafe test.tex

그 결과: perltexsortexample.png

와~ 보기만 해도 신납니다. :D --Progress

4 보기2: DB와 연동한 List Plot 그리기

본 예제는 DB(MySQL)에 저장되어 있는 수치 데이터를 Perl로 추출하여 이를 PSTricks를 이용하여 List plot을 그리는 예제이다. 여기서 구현하려는 것은 List plot에서 전체 평균과 최대값, 을 perl로 산출하여 이를 바로 TeX으로 출력하는 기능을 주는 것이다. 여기 예제는 Linux에서 사용하는 것을 가정하고 test하였으나 Windows에서도 사용가능하리라 생각된다.

4.1 DB관련 사전 작업

본 예제를 따라 할 수 있도록 DB 생성에서 데이터 입력 그리고 추출까지를 보이기로 하겠다. 일단, localhost에 MySQL이 설치 되어 있다고 가정하고, 1. DB 접속 및 유저 생성
% mysql -h localhost -p -u root
Enter password: *****
mysql> GRANT ALL ON perltexdb.* TO 'ptuser'@'localhost' IDENTIFIED BY 'ptpass';
Query OK, 0 rows affected (0.09 sec)
mysql> CREATE DATABASE perltexdb;
Query OK, 1 row affected (0.08 sec)
mysql> quit
2. Table 생성 및 데이터 입력
% mysql -h localhost -p -u ptuser
Enter password: ptpass
mysql> USE perltexdb;
mysql> CREATE TABLE perfdata (num INT, value FLOAT);
mysql> INSERT INTO perfdata (num,value) VALUES(1, 10.21);
mysql> INSERT INTO perfdata (num,value) VALUES(2, 20.22);
mysql> INSERT INTO perfdata (num,value) VALUES(3, 30.23);
mysql> INSERT INTO perfdata (num,value) VALUES(4, 40.24);
mysql> INSERT INTO perfdata (num,value) VALUES(5, 50.25);
mysql> INSERT INTO perfdata (num,value) VALUES(6, 52.24);
mysql> INSERT INTO perfdata (num,value) VALUES(7, 30.23);
mysql> INSERT INTO perfdata (num,value) VALUES(8, 20.22);
mysql> INSERT INTO perfdata (num,value) VALUES(9, 10.21);
mysql> INSERT INTO perfdata (num,value) VALUES(10, 8.18);

4.2 DB에서 데이터 가져오기

Perl의 DBI module을 사용하여 PSTricks를 통해 Graph를 그릴 때 필요한 입력 data 파일을 생성한다. connect.pl :
#! /usr/bin/perl -w
# connect.pl - connect to the MySQL server

use strict;
use DBI;
my $dsn = "DBI:mysql:host=localhost;database=perltexdb";

my $mysqldbh = DBI->connect ($dsn, "ptuser", "ptpass")
    or die "Cannot connect to server\n";

my $mysqlsth= $mysqldbh->prepare(
    "SELECT num, value FROM perfdata"
);

open(DATAFH, ">perfdata.dat");
$mysqlsth->execute();

my $count = 0;
while (my @val = $mysqlsth->fetchrow_array ())
{
    print DATAFH "$val[0]\t$val[1]\n";
    ++$count;
}

$mysqlsth->finish();
print "$count rows were returned\n";
참고: 여기서 노련한 독자는 왜, 이와 같은 DB 연결 code 또한 perlTeX에서
구현하지 않았을까하는 의문이 있을 것이다. 사실 뒤에서 보이겠지만 connect.pl과 perlTeX code를 따로 사용하면 각각 실행해야하는 불편 함이 있는 것이 사실이다. 필자도 처음에는 perlTeX 내에서 connect.pl 과 같은 code를 추가하려 하였으나, DBI module이 C로 짜여져 있는 module이라서 그런지, embeded perl error가 발생하였다. 아직까지 이 문제가 perlTeX의 한계인지, 아니면 다른 방법이 있는지는 알 수 없으나 일단 문제를 우회하며 해결하는 것으로 정하였다.
-- 최근에 나온 version으로 실행해 보니, perltex.pl로도 정상적으로 perfdata.dat화일은 나오는 것을 확인하였습니다. --synapse connect.pl 실행 과 결과
$ perl connect.pl
10 rows were returned
$ cat perfdata.dat
1       10.21
2       20.22
3       30.23
4       40.24
5       50.25
6       52.24
7       30.23
8       20.22
9       10.21
10      8.18

4.3 perlTeX와 PSTricks를 이용하여 list plot graph 작성

여기서 처음에 말했듯이 단순히 graph만 작성하는 것이 아니라 주어진 데이터의 최대값, 평균을 함께 출력하는 code를 작성하는 것이 목적이다.
drawgraph.tex :
\documentclass[12pt]{report}
\usepackage{pst-plot}
\usepackage{perltex}

\perlnewcommand{\findmax}[1]{
    #! /usr/bin/perl -w
    use strict;
    open(PERFD, "<$_[0]");
    my ($maxday,$maxval) = (0,0);
    while(<PERFD>) {
        my ($day, $val) = split /\s+/, $_;
        if ($maxday == 0){
        ($maxday,$maxval) = ($day,$val);
        }
        if ($val > $maxval) {
            ($maxday,$maxval) = ($day,$val);
        }
    }
    $maxval= sprintf("%.2f",$maxval);
    my $returnstr="($maxday, $maxval)";
    return "\\rput(2,-2.7){MAX: $returnstr}";
}

\perlnewcommand{\findavg}[1]{
    #! /usr/bin/perl -w
    use strict;
    open(PERFD, "<$_[0]");

    my $numofdata=0;

    my $average=0;
    while(<PERFD>) {
        ++$numofdata;
        my ($day, $val) = split /\s+/, $_;
        $average += $val;
    }
    $average = $average / $numofdata;
    $average= sprintf("%.2f",$average);
    return "\\rput(7,-2.7){AVG: $average}";
}

\begin{document}

\pagestyle{empty}

\newcommand{\DFILE}{./perfdata.dat}

\readdata{\DATA}{./perfdata.dat}
\psset{xunit=1,yunit=0.8}
\begin{pspicture}(0,-2)(12,7)
    \psset{showpoints=true,dotsize=0.1,plotstyle=line,linewidth=1pt}
    \rput(0,7){Value}
    \rput(11.7,0){Num}
    \rput(5,-1.5){\bf{Example for perlTeX}}
    \listplot[plotstyle=line,yunit=0.08cm,dotscale=2,linecolor=green]{\DATA}
    \psaxes[dy=0.8cm,Dy=10,Dx=1]{->}(0,0)(11.10,6.5)
    \findmax{\DFILE}    % <--- \rput(3,-2.7){MAX: 최대값} 을 출력
    \findavg{\DFILE}    % <--- \rput(7,-2.7){AVG: 평균값} 을 출력
\end{pspicture}

\end{document}
위의 code를 통해 perlTeX의 대략적인 사용법을 익힐 수 있다. \perlnewcommand라는 perlTeX의 macro 정의를 통해 perl code를 latex 파일에 내장 시킬수 있는데, 항상 출력은 return \rput(2,-2.7){MAX: $returnstr}; 와 같이 latex code로 한다. 즉, perl이 latex code를 만들어 주는 것이다. 여기서 한가지 필자가 경험한 바를 예를 들어 덧붙이고자 한다. 위의 code에서 \findavg 함수에서의 return 값을 위에서와 같이 return \rput(2,-2.7){AVG: $returnstr}; 로 하지 않고, return $average; 과 같이 값만 반환하게 한 후, \findavg{\DFILE} 대신에 \rput(3,-2.7){AVG: \findavg{\DFILE}} 과 같이 할 수도 있을 것이다. 테스트 한 바로는 이렇게 해도 같은 결과를 얻을 수 있었다. 그런데, 좀더 복잡한 상황에서 이렇게 수치만 perlTeX를 통해 출력하게면, stack overflow error 를 발생하게 되는 경우가 발생하였다. (구체적으로 예를 들면, \psaxes[dy=0.8cm,Dy=10,Dx=1]{->}(0,0)(11.10,6.5) 에서 0.8cm이라는 값을 perlTeX의 내부 연산 code를 통해 얻어지도록 하고자 할 때, 그런 경험이있다.) 따라서 결론은, perlTeX를 사용할때는 가급적이면 수치 일부분 만 출력하여 latex code 화 하지 말고, 단위 latex code
전체를 위의 예와 같이 출력하여 하는 것이 바람직하다.

4.4 결과 얻어 내기

$ perltex --nosafe drawgraph.tex
$ dvips -E drawgraph.dvi -o drawgraph.eps
위에서 --nosafe 옵션은 perltex자체에서 가지고 있는 보안기능으로 파일 입출력등으로 기본적으로 차단하고 있는데, 여기서는 이를 허용하도록 하는 옵션이다.

출력 결과

drawgraph.png

%%% 다소 부족한 듯한 느낌이 듭니다만, perlTeX에 관심이 있으신 %%% 분들에게 조금이나마 도움이 되셨기를 바랍니다. %%% 2004.12.4 오인수

DeleteMe. 좋은 예제 감사합니다. :) --Karnes

5 질문

안녕하십니까? perl로 tex를 할 수 있다니 매우 좋아보입니다. 제가 일전에 ktug의 practical use를 정리해 볼려고 perl를 이용해서 parctical use부분을 down받아 본적이 있습니다. 그때는 한참 더 해보려고 했는데, 그만 시간과 능력이 딸려서 못하고 말았습니다. 그렇다면, 가령 다음과 같은 것도 가능한지요?

perl를 이용해서 위의 KtugWiki page를 down받고(title page에서 wikipage name를 받고 난후에 각각의 Pagename별로 위의 내용을 down받는다) 난후에 이 내용을 perl를 이용해서(wiki문법을 tex로 바꾸는데 perl를 이용해야 할 것 같습니다) tex로 바꿀수 있을까요? 어찌보면 그냥 perl로 다 할 수도 있을 일 같이도 생각은 듭니다만......

그런다고 해서 제가 wikipage를 down받아서 어찌 해 보겠다는 말은 아닙니다. 그래도 앞으로 점점더 wikipage가 많아지면, 언제가는 누군가에 의해서 이런한 일이 되어져야 하지 않을까? 생각해서 그냥 한번 생각나는데로 적어 보았습니다. wiki도 좋지만, 아무래도 제 나이(?)에는 그냥 책으로 한권 가지고 있는 것도 좋습니다.

여기에 이런 내용이 어울리지 않으면 지우셔도 관계없습니다. --synapse

6 질문에 대한 저의 생각(오인수)

저도 wiki를 보면서, TeX의 미려한 출력과 비교해 보면 많이 가독성이 떨어지는 것이 사실이라 synapse 님과 같은 생각을 할 때가 있습니다. 위와 같이 구현하는 것은 충분히 가능한 일이라고 생각합니다. perl의 text processing 능력으로 충분할 것이라고 생각되고, tex source를 web page로 변환하는 것이 비슷한 예제라고 생각됩니다. 구체적 구현은 좀더 생각해 봐야 겠지만, 가능하다는데 무게를 두고 싶습니다. %%% 오인수 2004.12.4

감사합니다. 그런데 이미 wiki에서는 tex문서를 변환하고 있습니다.(완전한 변환은 아니구요) 물론 제가 써본 wiki라고 해봐야 wikix뿐이지만요.제가 얼마전에 조희대님의 도움으로 wikiX에서 tex문서를 wiki로 변환하기는 했습니다. 물론 전적으로 조희대님이 다 해 주셨지만은요?. 반대로 wiki에서 tex로 반환하는 것도 그리 어려지는 않을 것 같은데요? 어찌보면 더 쉬울수도 있을듯 싶기는 합니다. 그냥 생각에 wiki문법이라고 해봐야 별로 되지 않기 때문에.... tex문법에 비하면요..... 이번 기회에 조희대님께 한번 여쭈어 볼까요? 그런데 이일은 아무래도 karnes님의 허가가 있어야 하지 않을까 생각합니다. 그런데 용두사미가 되지 않을까? 걱정만 앞서는군요.... --synapse

^
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2008-01-11 00:52:35
Processing time 0.0573 sec