% Erstellungskommandos siehe unten !! \documentclass[12pt]{article} \usepackage{noweb} %\usepackage[T1]{fontenc}\language0\usepackage{a4} \usepackage[roman8]{inputenc}\language1\usepackage{a4wide} \textwidth=16.5cm\oddsidemargin0mm \textheight=23cm\oddsidemargin0mm \topmargin=-15mm \parindent=0mm \noweboptions{webnumbering,smallcode,longchunks} \sloppy \author{Hans Peter Wolf\\[2cm] \normalsize [[email: pwolf@wiwi.uni-bielefeld.de]]\\ \normalsize Bereich fÏr Statistik und Datenverarbeitung\\ \normalsize FakultÌt fÏr Wirtschaftswissenschaften\\ \normalsize UniversitÌt Bielefeld} \title{Ein Verschlag zur FormelfÏllung} \date{08.05.2000, [[R/formfill/ff3.rev]]} \begin{document} \maketitle \renewcommand{\contentsname}{\"Uberblick} \tableofcontents @ \section{Problemstellung} Statistische Formeln erzeugen bei Lernenden bisweilen UnverstÌndnis. Besonders auch deshalb, weil sie -- die Leidenden -- bei eigenen Auswertungen zu anderen Ergebnissen kommen. Deshalb kann eine VorfÏhrung der Auswertung hilfreich sein. Zur Erstellung einer solchen Demonstration ist ein Werkzeug denkbar, das fÏr spezifische Datenkonstellationen Schritte auf dem Weg zum Ziel in Form von Zwischenergebnissen zeigt. Mit einem solchen Werkzeug lieÞen sich auÞerdem vorher definierte Ergebnis-Formulare fÏllen, die dem sprÎden [[R]]-Output ein angemessenes Outfit verleihen. @ % START \section{Ein Beispiel, was gehen sollte} \newenvironment{formfill}[2]{\input{#1}}{} \begin{formfill}{ffbsp1.tex}{ Betrachten wir zun\"achst ein sehr kleines Beispiel. Es soll zu einem vorgegebenen $\alpha$ der Prozentpunkt $z_{1-\alpha/2}$ der Standardnormalverteilung berechnet werden. Je nach $\alpha$ ergibt sich nat\"urlich ein anderer Wert. Nehmen wir zum Beispiel an, es sei $\alpha=$ #alpha#. Wie lautet dann die gesuchte Wahrscheinlichkeit? Hier ist die Antwort: \[ z=z_{1-\alpha/2}=z_{#1-alpha/2#}= #z# \] #: alpha<-0.01 z <-qnorm(1-alpha/2) :# }\end{formfill} Man mÎchte natÏrlich nur an einer einzigen Stelle den Wert fÏr $\alpha$ festlegen, dann soll simsalabim auf Knopfdruck der Text mit den richtigen Zahlen {\em gefÏllt} vorliegen. Dieses Beispiel ist vielleicht etwas zu niedlich, um den gewÏnschten Effekt zu verdeutlichen. Deshalb betrachten wir einer Anregung von DT folgend ein Konfidenzintervall f\"ur den Parameter $p$ einer Bernoulli-Verteilung ${\cal B}(1,p)$, das sich gem\"a{\ss} \[ \mbox{KI}= \frac{1}{ n + z^2 } \left( n \hat p + \frac{1} {2}\pm z \sqrt{ n \hat p (1-\hat p) +\frac{ z^2} {4}} \right) \] berechnen lÌÞt. @ \begin{formfill}{ffbsp2.tex}{ #: n <-69 p <-0.768 conf <-0.99 alpha<-(1-conf) z <-qnorm(1-alpha/2) :# Nach einem Beispiel von Schlittgen errechnet sich f\"ur $n=$ #n# und $\hat p=$ #p# ein #1-alpha#\%-Konfidenzintervall wie folgt: \[ \begin{array}{r@{=}l} KI{}_{0.99}(p) & \frac{1}{#n#+#z#^2} \left( #n#\times#p# +\frac{#z#^2}{2}\pm #z#\sqrt{#n#\times#p#(1-#p#)+\frac{#z#^2}{4}} \right) \\& \frac{1}{#n + z ^2#} \left( #n * p# + #z^2/ 2# \pm #z#\sqrt{#n * p*(1- p)# + #z^2/4# } \right) \\& #1 /(n + z ^2)# \left( #n * p + z^2/ 2# \pm #z#\sqrt{#n * p*(1- p) + z^2/4# } \right) \\& #1 /(n + z ^2)# \left( #n * p + z^2/ 2# \pm #z#\times#sqrt(n * p*(1- p) + z^2/4 ) # \right) \\& #1 /(n + z ^2)# \left( #n * p + z^2/ 2# \pm #z * sqrt( n * p*(1- p) + z^2/4 ) # \right) \\& [#1/(n + z^2)*(n*p + z^2/2 - z * sqrt(n*p*(1- p) + z^2/4))#, #1/(n + z^2)*(n*p + z^2/2 + z * sqrt(n*p*(1- p) + z^2/4))#] \end{array} \] }\end{formfill} % ENDE @ Diese kleinen Umrechnungsschritte kann jeder schnell nachrechnen. Mit Hilfe des gedachten Werkzeugs lieÞen sich fÏr beliebige andere Datenkonstellationen sofort entsprechende FÏllergebnisse erstellen. Soweit die Wunschwelt. @ \section{Ein konzeptioneller Vorschlag} Der beschriebene Wunsch soll noch vor Weihnachten in ErfÏllung gehen. Deshalb folgt sogleich ein Umsetzungsvorschlag. Nach diesem Vorschlag lÌÞt sich in einer Rohdatei (dem \LaTeX-Dokument) eine neu entwickelte Umgebung verwenden, in der Texte mit auszuwertenden [[R]]-Anweisungen gespickt werden kÎnnen. Eine [[R]]-Funktion liest diese Umgebungen, wertet die gefundenen Anweisungen aus und schreibt das Ergebnis in eine Hilfsdatei. Der \LaTeX-Formatierer bettet die erstellte Hilfsdatei an Stelle der Umgebung in den Gesamttext ein. @ \section{Was der Anwender zu tun hat} Was der Anwender zu tun hat, wird zunÌchst allgemein und dann noch einmal anhand der vorliegenden Datei [[ff3.rev]] beschrieben. \begin{enumerate} \item ZunÌchst ist die neue Umgebung mit dem Namen [[formfill]] zu definieren: \begin{verbatim} \newenvironment{formfill}[2]{\input{#1}}{} \end{verbatim} \item Mit dieser neuen Umgebung lÌÞt sich ein Abschnitt beschreiben, deren Auswertungsergebnis in einer Hilfsdatei abgelegt werden. Dazu muÞ der Name der Hilfs-\TeX-Datei der Umgebung mitgegeben werden. Wie an der Definition der Umgebung zu erkennen ist, wird der Inhalt der Hilfsdatei bei der Formatierung (siehe: \verb+\input+) integriert. Als zweiter Parameter ist dieser Umgebung die Rohform des zu fÏllenden Abschnittes mitzugeben. Dieser Parameter wird bei der Formatierung nicht benutzt, so daÞ er durchaus Sonderzeichen enthalten kann. Der Body der Umgebung, sonst ueblicherweise das Fleisch des GerÏstes, bleibt leer. \item Die Rohform eines zu fÏllenden Abschnitts kann drei verschiedene QualitÌten enthalten: \begin{itemize} \item Klartext, der spÌter eins zu eins im formatierten Papier enthalten ist, \item [[R]]-Zuweisungen, die nicht ausgedruckt werden sollen, aber fÏr die zu ersetzenden Anweisungen Hilfvariablen bereitstellen, \item und [[R]]-Anweisungen, die spÌter durch ihre Werte ersetzt sein sollen. \end{itemize} BlÎcke von [[R]]-Zuweisungen beginnen mit Zeilen, die die Zeichenfolge: [[#:]] enthalten und werden durch Zeilen beendet, in denen das Zeichenpaar [[:#]] zu finden ist. Durch ihre Werte zu ersetzende [[R]]-Anweisungen werden durch das Umschaltzeichen [[#]] von normalen Textzeichen abgegrenzt, wie bei \TeX\ Formeln im Text durch Klammerung in [[$]]-Zeichen getrennt werden. \item Zur Umsetzung der im \LaTeX-Dokument beschriebenen ErsetzungswÏnsche wird in diesem Papier die [[R]]-Funktion [[ff]] beschrieben: <<*>>= <> @ Diese Funktion muÞ in den [[R]]-Interpreter geladen und mit dem Quelldateinamen als Argument gestartet werden. FÏr jede [[formfill]]-Umgebung erstellt [[ff]] die vereinbarte(n) Hilfsdatei(en) mit den aufbereiteten Texten. \item Nun kann die Quelldatei ge\LaTeX t werden. \item Probieren geht vor studieren. \end{enumerate} @ Um eine noch bessere Vorstellung von den zu erledigenden TÌtigkeiten zu bekommen, wollen wir eine Auf\-listung von konkreten Handlungsanweisungen anfÏgen. @ \begin{enumerate} \item Die Definition der Umgebung muÞ irgendwo vorn in der Quelldatei stehen. Hier ist der Code: \begin{verbatim} \newenvironment{formfill}[2]{\input{#1}}{} \end{verbatim} \item Einen zu fÏllenden Abschnitt, dessen Bearbeitungsergebnis in der Datei [[ffbsp1.tex]] abgelegt werden soll, leiten wir fÏr ein mit: \verb+\begin{form+[[fill}{ffbsp1.tex}{]] \item Im Text wollen wir beispielsweise den Wert der Formel $z_{1-\alpha/2}$ eingesetzt bekommen. Dazu lassen wir zum Beispiel die Variable [[z]] auswerten, die im nÌchsten Schritt definiert wird: \begin{verbatim} ... Wahrscheinlichkeit? Hier ist die Antwort: \[ z=z_{1-\alpha/2}=z_{#1-alpha/2#}=#z# \] \end{verbatim} \item Die Hilfsvariablen [[z]] und [[alpha]] mÏssen wir definieren: \begin{verbatim} #: alpha<-0.01 z <-qnorm(1-alpha/2) :# \end{verbatim} \item Am Ende des zu fÏllenden Absatzes mÏssen wir diesen beenden und schreiben: \verb+}\end{form+[[fill}]] \item Wir lassen [[ff(ff3.rev)]] von [[R]] durch einen Batchaufruf: \begin{verbatim} echo "source(\"ff3.sch\");ff(\"ff3.rev\")" | R BATCH \end{verbatim} oder per Hand veranlaÞt auswerten. Ist [[ff]] in der Umgebung bereits erreichbar, muÞ sie natÏrlich nicht geladen werden. \item \verb+latex ff3+ \item Weiterverarbeitung wie gewohnt. \end{enumerate} @ Vielleicht klingt das Prozedere nach dem ersten HinhÎren kompliziert, jedoch sind nur drei Dinge zu tun: Schreibe den Quellfile, starte [[ff]] und \TeX e wie Ïblich. @ \section{Die LÎsung fÏr einzelne FÏll\-ab\-schnitte\\-- die innere Funktion} Wir wollen zur Umsetzung der WÏnsche bzw.\ von [[ff]] zunÌchst ein leichteres Problem lÎsen: Gegeben sei eine Variable, auf der als Elemente die Zeilen eines auszuwertenden und zu fÏllenden Rohabschnittes stehen. Dann soll die Funktion [[ff.local]] die beschriebenen Definitionen umsetzen, die zu ersetzenden AusdrÏcke auswerten und ersetzen und das Ergebnis in den angegebenen File schreiben. % ----------------------- ------------------------------------------ % @ Die Funktion [[ff.local]] ersetzt, wie oben schon beschrieben, in einem Text jede in zwei {\em Fluchtsymbole} oder besser {\em Trennzeichen} eingeschlossene Zeichenkette durch ihren Wert, wie R ihn berechnet. Das Default-Fluchtzeichen ist der Lattenzaun. @ Beispiel: [[#2+2#]] wird ÏberfÏhrt in 4. Um auch mit verschiedenen Variablen operieren zu kÎnnen, werden vor der Evaluation der zu ersetzenden AusdrÏcke alle Terme ausgewertet, die mit durch Fluchtsymbol Doppelpunkt beginnen und mit Doppelpunkt Fluchsymbol enden. So kann mit \begin{verbatim} #: x <- 1:10 :# \end{verbatim} die Variable [[x]] belegt und in [[#sum(x)#]] verwendet werden. FÏr weitere Verwendungen lÌÞt sich zum Beispiel die Variable [[y]] als Quadrat von [[x]] einfÏhren: \begin{verbatim} #: y <- x*x :# \end{verbatim} Als Nebenbedingung mÏssen zu ersetzende AusdrÏcke innerhalb einer Zeile stehen. Erlaubt sind auch mehrere AusdrÏcke pro Zeile. Mehrere Definitionen dÏrfen dagegen nicht in einer Zeile auftauchen. @ Der Funktion [[ff.local]] werden als erstes Argument die Textzeilen [[tz]] Ïbergeben. Als zweiter Parameter ist der Name der Outputdatei zu Ïbergeben. Weiter folgen die Genauigkeit des Ergebnisses und das ausgewÌhlte Fluchtsymbol. FÏr etwaige ProblemfÌlle kann die Funktion mit der Option [[debug=T]] gestartet werden, mit der an zentralen Stellen die Funktion [[browser]] zur Inspektion aufgerufen wird. Die Syntax kann der Kopfzeile entnommen werden. <>= ff.local<- function(tz,out.file="tmpout.tex",path="",digits=4,escape.symbol="#",debug=T){ <> } @ Innerhalb der Funktion werden zunÌchst die Definitionen und dann die ErsetzungswÏnsche umgesetzt. Zum SchluÞ wird das Ergebnis in der Hilfsdatei abgelegt und eine kurze Meldung ausgegeben. <>= if(debug) browser() <> <> if(0>= <> repeat{ <> <> <> if(debug){print("Teil Definitionsauswertung, Ende repeat");browser()} } <> @ Auf [[tz]] stehen Zeilenweise die Zeilen. Durch eine schnelle Inspektion lassen sich alle AnfÌnge und Enden von DefinitionsblÎcken finden. FÏr die spÌtere Entfernung der Definitionen von [[tz]] werden die Grenzen auf [[ff.defs.pos]] festgehalten. <>= ff.begin<-grep(paste(escape.symbol,":",sep=""),tz) ff.end <-grep(paste(":",escape.symbol,sep=""),tz) ff.defs.pos<-cbind(ff.begin,ff.end) @ Wenn keine weiteren Definitionen mehr gefunden werden, kann die Definitionsauswertung abgebrochen werden. <>= if(length(ff.begin)==0 ) break @ In diesem Abschnitt werden alle Definitionen des nÌchsten Definitionsblocks extrahiert. Zuerst wird der Block auf [[ff.defs]] abgelegt. [[ff.begin]] und [[ff.end]], die die Blockgrenzen halten, werden verkÏrzt. Die Zeichenketten [[#:]] bzw.\ [[:#]] stÎren die Evaluation und werden entfernt, so daÞ am SchluÞ auf [[ff.defs]] die zu aktivierenden Definitionen stehen. <>= ff.defs<-tz[ff.begin[1]:ff.end[1]] ff.begin<-ff.begin[-1]; ff.end<-ff.end[-1] ff.chars<-substring(ff.defs[1],1:nchar(ff.defs[1]),1:nchar(ff.defs[1])) ff.von <-seq(ff.chars)[ff.chars==escape.symbol&c(ff.chars[-1]," ")==":"] ff.defs[1]<-substring(ff.defs[1],ff.von+2) ff.h<-1:nchar(ff.defs[ff.length<-length(ff.defs)]) ff.chars<-substring(ff.defs[ff.length],ff.h,ff.h) ff.bis <-seq(ff.chars)[c(ff.chars[-1]," ")==escape.symbol&ff.chars==":"] ff.defs[ff.length]<-substring(ff.defs[ff.length],1,ff.bis-1) @ Alle Definitionen des extrahierten Blockes mÏssen evaluiert werden. <>= for(ff.d in ff.defs){ if(debug){print("Definitionsteil, vor Evaluation"); print(ff.d)} eval(parse(text=ff.d)) } @ Von [[tz]] werden die Zeilen mit den DefinitionsblÎcken entfernt. <>= for(ff.h in 1:length(ff.defs.pos[,1])) tz<-tz[-(ff.defs.pos[ff.h,1]:ff.defs.pos[ff.h,2])] @ Als zweites sind die ErsetzungsauftrÌge umzusetzen. Dazu ist die nÌchste Zeile mit einem Ersetzungsauftrag zu suchen. Der nÌchste Auftrag ist zu evaluieren, und das Ergebnis ist zurÏckzuschreiben. <>= <> repeat{ <> <> ff.found<-T <> if(debug){print("Ersetzungsteil, Ersetzungskandidaten ermittelt");browser()} if(ff.found){ <> <> <> } <> } @ Als Vorbereitung lassen sich leicht alle Zeilen mit Fluchtsymbolen finden, die potentielle Kandidaten fÏr Ersetzungen darstellen. <>= ff.begin.end<-grep(escape.symbol,tz) @ Wenn keine Ersetzungen (mehr) gefunden werden, kann die Ersetzungsarbeit beendet werden. <>= if(length(ff.begin.end)==0) break @ Die nÌchste potentielle Zeile wird zuerst in ihre Zeichen zerlegt. <>= ff.repl <-tz[ff.begin.end[1]] ff.chars<-substring(ff.repl,1:nchar(ff.repl),1:nchar(ff.repl)) @ Auf [[ff.positions]] werden die Stellen der Fluchtsymbole der potentiellen Zeile abgelegt. Dann folgen einige weitere ÛberprÏfungen, um auch sicher zu sein, daÞ eine Ersetzung notwendig ist. Ist dies nicht der Fall, wird [[ff.found]] auf [[F]] gesetzt. <>= ff.positions<-seq(ff.chars)[ff.chars==escape.symbol] if(length(ff.positions)<2) ff.found<-F if(ff.chars[ff.positions[1]+1]==":") ff.found<-F if(0!=length(ff.positions)%%2) ff.found<-F @ Wenn [[ff.found]] wahr ist, werden die Ersetzungen der Zeile extrahiert. Dabei dÏrfen die Trennzeichen selbst nicht Ïbernommen werden. <>= ff.positions<-matrix(ff.positions,2) ff.eval <-substring(ff.repl,ff.positions[1,]+1,ff.positions[2,]-1) @ Da pro Zeile mehrere Ersetzungen notwendig sein kÎnnen, geschieht die Abarbeitung in einer Schleife. <>= ff.out<-NULL for(ff.e in ff.eval){ if(debug) {print("Ersetzungsteil, vor Evaluation von:"); print(ff.e)} ff.out<-c(ff.out,eval(parse(text=ff.e))) } @ Die berechneten Ersetzungen werden auf die Variable [[tz]] zurÏckgeschrieben. Dabei wird die vorgegebene Zahlengenauigkeit berÏcksichtigt. Es erschien praktisch, zur Vermeidung von SonderfÌllen die aktuelle Zeile [[ff.chars]] vorn und hinten um jeweils einen Buchstaben zu verlÌngern. Diese Zugaben werden jedoch spÌter wieder entfernt. <>= ff.out<-as.character(signif(ff.out,digits)) ff.chars<-c("a",ff.chars[0==cumsum(ff.chars==escape.symbol)%%2],"z") ff.chars<-paste(ff.chars,collapse="") if(debug){print("Ersetzungsteil, vor strsplit");browser()} @ Die zusammengefÏgte Zeile wird an den Stellen der Fluchtsymbole aufgebrochen und als Zeile unter die Ersetzungen geschrieben. Die spaltenweise Betrachtung der so entstandenen Matrix liefert nach Entfernung des ersten Elementes, nach erneutem ZusammenfÏgen und nach Entfernung des ersten und letzten Zeichens das gewÏnschte Ergebnis. <>= ff.chars<-strsplit(ff.chars,escape.symbol)[[1]] ff.chars<-rbind(c(" ",ff.out),ff.chars)[-1] ff.chars<-paste(ff.chars,collapse="") ff.repl <-substring(ff.chars,2,nchar(ff.chars)-1) @ Das ZurÏckschreiben erfordert eine letzte Anweisung. <>= tz[ff.begin.end[1]]<-ff.repl @ Haben wir eine Zeile erledigt, kann sie aus der Menge der zu bearbeitenden Zeilen entfernt werden, also von [[ff.begin.end]]. <>= ff.begin.end<-ff.begin.end[-1] @ \section{Eine allgemeine LÎsung fÏr viele FÏll\-ab\-schnitte\\ -- die ÌuÞere Funktion} Nachdem im Prinzip das Problem gelÎst ist, muÞ noch eine passende Einbettung, die Funktion [[ff]] selbst, entworfen werden. In dieser ist die oben beschriebene Funktion zu verdrahten, die zu bearbeitende Datei (ggf.\ auch der Pfad) ist einzulesen, die FÏllteile ([[formfill]]-Umgebungen) sind zu finden und die FÏllauftrÌge mÏssen abgehandelt werden. Neben dem Namen der Quelldatei kÎnnen die Zahlengenauigekeit und das Fluchtsymbol (Defaults: 4 bzw.\ [[#]]) gesetzt werden. Ein eventueller Debug-Wunsch wird Ïber den Parameter [[debug]] Ïbergeben. <>= ff<-function(in.file,path="",digits=4,escape.symbol="#",debug=F){ <> <> <> <> <> <> } @ Wenn kein Pfad explizit angegeben ist, sollten die Hilfdateien spÌter in dem Verzeichnis zu finden sein, aus dem der Quellfile stammt. <>= if(0==nchar(path)){ ff.h<-unlist(strsplit(in.file,"/")) path<-paste(ff.h[-length(ff.h)],collapse="/") }else{ in.file<-paste(path,in.file,sep="/") } @ Die Datei [[in.file]] wird zeilenweise als Text eingelesen. <>= ff.tz<-scan(in.file,"",sep="\n") @ FÏllteile beginnen mit [[\begin]][[{formfill}]] und werden mit [[\end]][[{formfill}]] abgeschlossen. Wenn keine solche Umgebung gefunden wird, soll der gesamte File abgearbeitet werden. FÏr das weitere muÞ der erste Umgebungsparameter mit den Hilfsdateinamen extrahiert werden. AuÞerdem sind Umgebungskopf und -ende zu entfernen. Es wird eine kurze Meldung Ïber die gefundenen Dateinamen ausgegeben. <>= ff.pos<-grep("\\\\begin\{formfill\}",ff.tz) if(length(ff.pos)==0){ ff.pos<-matrix(c(1,length(ff.tz)),1,2);ff.names<-"tmpout.tex" }else{ ff.names<-sub("\\\\begin\\{formfill\\}","",ff.tz[ff.pos]) ff.names<-gsub("\{","",ff.names) ff.names<-unlist(strsplit(ff.names,"\}")) ff.pos<-cbind(ff.pos,grep(paste("\\\\end\{","formfill\}",sep=""),ff.tz)) } cat("new file(s):",paste(ff.names,collapse=" "),"\n") @ Mit Hilfe der Funktion [[ff.local]] ist die Bearbeitung der gefundenen FÏllteile kein Problem mehr. <>= for(ff.n in seq(along=ff.names)){ ff.local( ff.tz[(ff.pos[ff.n,1]+1):(ff.pos[ff.n,2]-1)], out.file=ff.names[ff.n], path=path, digits=digits, escape.symbol=escape.symbol, debug=debug ) } @ Damit ist die Umsetzung des Vorschlag zur ErfÏllung des FormelfÏllungswunsches abgeschlossen. @ \section{BehelfsmÌÞige Implementation der Funktionen [[sub]], [[gsub]] und [[grep]] fÏr {\sc S-Plus}} <>= if(!exists("sub")){ # RegExpr, ignore.case und extended nicht unterstuetzt gsub<-sub<-function(pattern,replacement,x,ignore.case=F,extended=TRUE){ x.name<-substitute(x) pattern<-substring(pattern,1:nchar(pattern),1:nchar(pattern)) if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="{" )))pattern<-pattern[!h] if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="}" )))pattern<-pattern[!h] if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="\\")))pattern<-pattern[!h] if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="b" ))) {pattern[h]<-"\b"; pattern<-pattern[-(seq(along=pattern)[h]+1)]} if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="e" ))) {pattern[h]<-"\e"; pattern<-pattern[-(seq(along=pattern)[h]+1)]} pattern.n<-length(pattern) for(i in 1:length(x)){ h.n<-nchar(x[i]); cand<-pattern[1]==(h<-substring(x[i],1:h.n,1:h.n)) if(any(cand)){ cand<-(1:h.n)[cand]; substitution<-F for(j in rev(cand)){ if((j-1+pattern.n)>h.n) next if(all(pattern==h[(j-1)+seq(along=pattern)])){ h<-c(if(j>1)h[1:(j-1)], replacement, if((j-1+pattern.n)>= if(!exists("strsplit")){ # RegExpr, ignore.case, extended, value nicht unterstuetzt grep<-function(pattern, x, ignore.case=FALSE, extended=TRUE, value=FALSE){ x.name<-substitute(x) pattern<-substring(pattern,1:nchar(pattern),1:nchar(pattern)) if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="{" )))pattern<-pattern[!h] if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="}" )))pattern<-pattern[!h] if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="\\")))pattern<-pattern[!h] if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="b" ))) {pattern[h]<-"\b"; pattern<-pattern[-(seq(along=pattern)[h]+1)]} if(any(h<-(pattern=="\\"&c(pattern[-1]," ")=="e" ))) {pattern[h]<-"\e"; pattern<-pattern[-(seq(along=pattern)[h]+1)]} pattern.n<-length(pattern) found<-NULL for(i in 1:length(x)){ h.n<-nchar(x[i]); cand<-pattern[1]==(h<-substring(x[i],1:h.n,1:h.n)) if(any(cand)){ cand<-(1:h.n)[cand] for(j in rev(cand)){ if((j-1+pattern.n)>h.n) next if(all(pattern==h[(j-1)+seq(along=pattern)])){ found<-c(found,i);break } } } } return(found) } ;assign("grep",grep,frame=1)} @ <>= if(!exists("strsplit")){ strsplit<-function(x,split){ out<-NULL for(i in x){ hh<-split==(h<-substring(i,1:nchar(i),1:nchar(i))) if(!any(hh)){out<-c(out,list(i));next} pos<-c(0,seq(along=hh)[hh]) new<-unlist(lapply(pos,function(x,charvec)substring(charvec,x+1),i)) anz<-diff(c(pos,length(h)+1))-1 new<-new[anz>0]; anz<-anz[anz>0] new<-unlist(lapply(seq(along=anz), function(x,vec,anz)substring(vec[x],1,anz[x]),new,anz)) out<-c(out,list(new)) } return(out) };assign("strsplit",strsplit,frame=1)} @ \small \newpage @ \section{Anhang A: Die beiden Hilfsdateien} \input{ffhfiles.tex} \newpage @ \section{Anhang B: Ein Ausschnitt aus dem Quellfile} \input{ffbspsrc.tex} @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \end{document} @ # Einige Kommandos zur Erzeugung der Hilfdateien fuer diesen rev-File. # weave und tangle revweb ff3 # Erzeugung des File mit dem Quellcode: Anhang A gawk 'BEGIN {print "\\begin\{verbatim\}"};\ /START/{x=1;next};\ /ENDE/{x=0;next};\ {if(x==1){print $0}else{next}};\ END {print "\\end\{verbatim\}"}' ff3.rev > ffbspsrc.tex # Erzeugung der Files mit den ersetzten Anweisungen echo "source(\"ff3.sch\");ff(\"ff3.rev\")" | R BATCH # Erzeugung des File mit dem Quellcode der Input-Files: Anhang B echo "{\\\\tt ffbsp1.tex:} \\\\begin{verbatim}" > ffhfiles.tex cat ffbsp1.tex >> ffhfiles.tex echo "\\\\end{verbatim} {\\\\tt ffbsp2.tex:} \\\\begin{verbatim}">>ffhfiles.tex cat ffbsp2.tex >> ffhfiles.tex echo "\\\\end{verbatim}" >> ffhfiles.tex # texen latex ff3; latex ff3