marc4j4r 0.1.6 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/README.rdoc +17 -0
  2. data/Rakefile +26 -13
  3. data/VERSION +1 -1
  4. data/jars/marc4j.jar +0 -0
  5. data/lib/marc4j4r/controlfield.rb +32 -0
  6. data/lib/marc4j4r/datafield.rb +196 -0
  7. data/lib/marc4j4r/reader.rb +71 -0
  8. data/lib/marc4j4r/record.rb +214 -0
  9. data/lib/marc4j4r/writer.rb +29 -0
  10. data/lib/marc4j4r.rb +26 -485
  11. data/lib/original_monolithic_file.rb +518 -0
  12. data/spec/batch.dat +1 -0
  13. data/spec/batch.txt +193 -0
  14. data/spec/batch.xml +13 -0
  15. data/spec/controlfield_spec.rb +40 -0
  16. data/spec/datafield_spec.rb +56 -0
  17. data/spec/one.dat +1 -0
  18. data/spec/one.txt +17 -0
  19. data/spec/one.xml +4 -0
  20. data/spec/reader_spec.rb +49 -0
  21. data/spec/record_spec.rb +101 -0
  22. data/{test/helper.rb → spec/spec_helper.rb} +9 -5
  23. metadata +74 -80
  24. data/.document +0 -5
  25. data/.gitignore +0 -21
  26. data/README.markdown +0 -41
  27. data/doc/ControlFieldImpl.html +0 -314
  28. data/doc/DataFieldImpl.html +0 -875
  29. data/doc/Java/OrgMarc4j/MarcReader.html +0 -184
  30. data/doc/MARC4J4R/Reader.html +0 -245
  31. data/doc/MARC4J4R.html +0 -281
  32. data/doc/RecordImpl.html +0 -686
  33. data/doc/SubfieldImpl.html +0 -252
  34. data/doc/_index.html +0 -153
  35. data/doc/class_list.html +0 -36
  36. data/doc/css/common.css +0 -1
  37. data/doc/css/full_list.css +0 -50
  38. data/doc/css/style.css +0 -268
  39. data/doc/file.README.html +0 -90
  40. data/doc/file_list.html +0 -38
  41. data/doc/frames.html +0 -13
  42. data/doc/index.html +0 -90
  43. data/doc/js/app.js +0 -99
  44. data/doc/js/full_list.js +0 -106
  45. data/doc/js/jquery.js +0 -19
  46. data/doc/method_list.html +0 -219
  47. data/doc/top-level-namespace.html +0 -87
  48. data/jars/MarcImporter.jar +0 -0
  49. data/test/batch.seq +0 -118
  50. data/test/bench.rb +0 -63
  51. data/test/one.dat +0 -1
  52. data/test/one.seq +0 -30
  53. data/test/one.xml +0 -55
  54. data/test/test_marc4j4r.rb +0 -76
@@ -0,0 +1,518 @@
1
+ unless defined? JRUBY_VERSION
2
+ raise "Only works under JRUBY"
3
+ end
4
+
5
+ begin
6
+ include_class Java::org.marc4j.marc.impl.RecordImpl
7
+ rescue NameError => e
8
+ jardir = File.join(File.dirname(__FILE__), '..', 'jars')
9
+ require "#{jardir}/marc4j.jar"
10
+ end
11
+
12
+ require 'set'
13
+
14
+
15
+ # Re-open the MarcReader interface, define #each and include Enumerable
16
+ #
17
+ # We also automatically call #hashify on the records that stream through
18
+ # #each in order to speed up RecordImpl#[] when (a) doing many operations on a single
19
+ # record, and (b) we're not worried about interleaved tags (e.g., a 520 followed by a 510 followed
20
+ # by another 520)
21
+
22
+ module Java::OrgMarc4j::MarcReader
23
+ include Enumerable
24
+
25
+ # Return the next record, after calling #hashify on it
26
+ def each(hashify=true)
27
+ while self.hasNext
28
+ r = self.next
29
+ r.hashify if hashify
30
+ yield r
31
+ end
32
+ end
33
+ end
34
+
35
+
36
+ module MARC4J4R
37
+
38
+ # Do some simple substitutions to make things prettier. After this,
39
+ # we can use MARC4J4R::Record instead of Java::org.marc4j.marc.impl::RecordImpl
40
+
41
+ Record = Java::org.marc4j.marc.impl::RecordImpl
42
+ ControlField = Java::org.marc4j.marc.impl::ControlFieldImpl
43
+ DataField = Java::org.marc4j.marc.impl::DataFieldImpl
44
+ SubField = Java::org.marc4j.marc.impl::SubfieldImpl
45
+
46
+
47
+ # Add some sugar to the MarcReader interface
48
+ #
49
+ # Adjust the interface so that a #new call to any implementations that
50
+ # implement it can take a java.io.InputStream, ruby IO obejct, or String
51
+ # (that will be interpreted as a filename) without complaining.
52
+ #
53
+ # The mechanism -- running module_eval on a string-representation of the
54
+ # new method in each of the hard-coded implementations of MarcReader
55
+ # (MarcStreamReader,MarcPermissiveStreamReader,MarcXmlReader) -- is ugly
56
+ # and deeply unsettling.
57
+ #
58
+ # @author Bill Dueber
59
+ #
60
+ # A string used to override the initializer for each stream reader
61
+ # Need to do it this ugly way because of the way java and ruby interact;
62
+ # can't just add it to the MarcReader interface the way I wanted to.
63
+
64
+ NEWINIT = <<-ENDBINDER
65
+ include Enumerable
66
+ alias_method :oldinit, :initialize
67
+ def initialize(fromwhere)
68
+ stream = nil
69
+ if fromwhere.is_a? Java::JavaIO::InputStream or fromwhere.is_a? Java::JavaIO::ByteArrayInputStream
70
+ stream = fromwhere
71
+ elsif fromwhere.is_a? IO
72
+ stream = fromwhere.to_inputstream
73
+ else
74
+ stream = java.io.FileInputStream.new(fromwhere.to_java_string)
75
+ end
76
+ if self.class == Java::org.marc4j.MarcPermissiveStreamReader
77
+ self.oldinit(stream, true, true)
78
+ else
79
+ self.oldinit(stream)
80
+ end
81
+ end
82
+ ENDBINDER
83
+
84
+ Java::org.marc4j.MarcStreamReader.module_eval(NEWINIT)
85
+ Java::org.marc4j.MarcPermissiveStreamReader.module_eval(NEWINIT)
86
+ Java::org.marc4j.MarcXmlReader.module_eval(NEWINIT)
87
+
88
+
89
+
90
+ # Get a marc reader of the appropriate type
91
+ # @param [String, IO, java.io.InputStream] input The IO stream (or filename) from which you want to read
92
+ # @param [:strictmarc, :permissivemarc, :marcxml] The type of MARC reader you want.
93
+ # @return [MarcReader] A MarcReader object with the syntactic sugar added in this file (e.g, each)
94
+ #
95
+ # @example Get a strict binary MARC reader for the file 'test.mrc'
96
+ # reader = MARC4J4R.reader('test.mrc')
97
+ #
98
+ # @example Get a permissive binary MARC reader
99
+ # reader = MARC4J4R.reader('test.mrc', :permissivemarc)
100
+ #
101
+ # @example Get a reader for an xml file
102
+ # reader = MARC4J4R.reader('test.xml', :marcxml)
103
+ #
104
+ # @example Get a reader based on an existing IO object
105
+ # require 'open-uri'
106
+ # infile = open('http://my.machine.com/test.mrc')
107
+ # reader = MARC4J4R.reader(infile)
108
+
109
+ def reader(input, type = :strictmarc)
110
+ case type
111
+ when :strictmarc then
112
+ return Java::org.marc4j.MarcStreamReader.new(input)
113
+ when :permissivemarc then
114
+ return Java::org.marc4j.MarcPermissiveStreamReader.new(input)
115
+ when :marcxml then
116
+ return Java::org.marc4j.MarcXmlReader.new(input)
117
+ when :alephsequential then
118
+ return MARC4J4R::AlephSequentialReader.new(input)
119
+ else
120
+ raise ArgumentError, "Reader type #{type} illegal: must be :strictmarc, :permissivemarc, :marcxml, or :alephsequential"
121
+ end
122
+ end
123
+ module_function :reader
124
+
125
+
126
+ # Implement an AlephSequential reader
127
+ class AlephSequentialReader
128
+ include Enumerable
129
+ def initialize(fromwhere)
130
+ stream = nil
131
+ if fromwhere.is_a? Java::JavaIO::InputStream
132
+ stream = fromwhere.to_io
133
+ elsif fromwhere.is_a? IO
134
+ stream = fromwhere
135
+ else
136
+ stream = File.new(fromwhere)
137
+ end
138
+
139
+ @handle = stream
140
+ end
141
+
142
+ def each
143
+ record = nil
144
+ currentID = nil
145
+
146
+ @handle.each_line do |l|
147
+ l.chomp!
148
+ next unless l =~ /\S/
149
+ vals = l.unpack('a9 a a3 c c a3 a*')
150
+ id, tag, ind1, ind2, data = vals[0], vals[2], vals[3], vals[4], vals[6]
151
+ # id, tag, ind1, ind2, junk, data = *(l.unpack('A10 a3 c c a3 A*'))
152
+ if id != currentID
153
+ if record
154
+ yield record
155
+ end
156
+ record = RecordImpl.new
157
+ currentID = id
158
+ end
159
+ if tag == 'LDR'
160
+ record.setLeader(Java::org.marc4j.marc.impl.LeaderImpl.new(data))
161
+ else
162
+ record << buildField(tag,ind1,ind2,data)
163
+ end
164
+ end
165
+ yield record
166
+ end
167
+
168
+
169
+ SUBREGEXP = /\$\$(.)/
170
+ def buildField (tag, ind1, ind2, data)
171
+ if Java::org.marc4j.marc.impl.Verifier.isControlField tag
172
+ return Java::org.marc4j.marc.impl.ControlFieldImpl.new(tag, data)
173
+ else
174
+ f = Java::org.marc4j.marc.impl.DataFieldImpl.new(tag, ind1, ind2)
175
+ data.split(SUBREGEXP)[1..-1].each_slice(2) do |code, value|
176
+ f.addSubfield Java::org.marc4j.marc.impl.SubfieldImpl.new(code[0].ord, value)
177
+ end
178
+ return f
179
+ end
180
+ end
181
+
182
+ end # End of class AlephSequentialReader
183
+
184
+ end
185
+
186
+
187
+ # Open up RecordImpl to add some sugar, including Enumberable as well
188
+ # @author Bill Dueber
189
+
190
+ class Record
191
+ include Enumerable
192
+
193
+ alias_method :<<, :addVariableField
194
+ alias_method :append, :addVariableField
195
+ alias_method :fields, :getVariableFields
196
+
197
+ # Export as a MARC-Hash, as described at
198
+ # http://robotlibrarian.billdueber.com/marc-hash-the-saga-continues-now-with-even-less-structure/
199
+ # @return A marc-hash representation of the record, suitable for calling .to_json on or whatever
200
+ def to_marchash
201
+ h = {}
202
+ h['type'] = 'marc-hash'
203
+ h['version'] = [1,0]
204
+ h['leader'] = self.leader
205
+
206
+ fields = []
207
+
208
+ self.getVariableFields.each do |f|
209
+ if f.controlField?
210
+ fields << [f.tag, f.value]
211
+ else
212
+ farray = [f.tag, f.indicator1 || ' ', f.indicator2 || ' ']
213
+ subs = []
214
+ f.each do |subfield|
215
+ subs << [subfield.code, subfield.value]
216
+ end
217
+ farray.push subs
218
+ fields << farray
219
+ end
220
+ end
221
+ h['fields'] = fields
222
+ return h
223
+ end
224
+
225
+ # Create a local hash by tag number; makes some stuff faster
226
+ # Called automatically if you use reader.each
227
+
228
+ def hashify
229
+ return if @hashedtags # don't do it more than once
230
+ @hashedtags = {}
231
+ self.getVariableFields.each do |f|
232
+ @hashedtags[f.tag] ||= []
233
+ @hashedtags[f.tag].push f
234
+ end
235
+ end
236
+
237
+ # Create a nice string of the record
238
+ def to_s
239
+ arr = ['LEADER ' + self.leader]
240
+ self.each do |f|
241
+ arr.push f.to_s
242
+ end
243
+ return arr.join("\n")
244
+ end
245
+
246
+ # Get the leader as a string (marc4j would otherwise return Leader object)
247
+ def leader
248
+ self.get_leader.toString
249
+ end
250
+
251
+
252
+ # Cycle through the fields in the order the appear in the record
253
+ def each
254
+ self.getVariableFields.each do |f|
255
+ yield f
256
+ end
257
+ end
258
+
259
+ # Get the first field associated with a tag
260
+ # @param [String] tag The tag
261
+ # @return [Field] The first matching field, or nil if none. Note that
262
+ # to mirror ruby-marc, this returns a single field
263
+
264
+ def [] tag
265
+ if defined? @hashedtags
266
+ if @hashedtags[tag]
267
+ return @hashedtags[tag][0]
268
+ else
269
+ return nil
270
+ end
271
+ else
272
+ return self.getVariableField(tag)
273
+ end
274
+ end
275
+
276
+
277
+ # Get a (possibly empty) list of fields with the given tag(s)
278
+ #
279
+ # @param [String, Array<String>] tags A string (or Array of strings) with the tags you're interested in
280
+ # @param [Boolean] originalorder Whether or not results should be presented in the original order within the
281
+ # record or with a two-column sort of (a) Order of the tag in the list of tags sent, (b) order within that tag
282
+ # in the record
283
+ # @return [Array<Field>] Either an empty list or a list of one or more matched fields will be returned.
284
+ #
285
+ # originalorder == false will use an internal hash and be faster in many cases (see #hashify)
286
+ #
287
+ # @example originalorder == false
288
+ # # Given a record that looks like
289
+ # # 010 $a 68027371
290
+ # # 035 $a (RLIN)MIUG0001728-B
291
+ # # 035 $a (CaOTULAS)159818044
292
+ # # 035 $a (OCoLC)ocm00001728
293
+ #
294
+ # r.find_by_tag(['035', '010']).each {|f| puts f.to_s}
295
+ # # 035 $a (RLIN)MIUG0001728-B
296
+ # # 035 $a (CaOTULAS)159818044
297
+ # # 035 $a (OCoLC)ocm00001728
298
+ # # 010 $a 68027371
299
+ #
300
+ # # The results are ordered first by tag as passed in, then by original order within the tag
301
+ #
302
+ # @example Just get all fields for a single tag
303
+ # ohThirtyFives = r.find_by_tag('035')
304
+ #
305
+ # @example Get a bunch of standard identifiers
306
+ # standardIDs = r.find_by_tag(['022', '020', '010'])
307
+ #
308
+ # @example originalorder == true
309
+ # r.find_by_tag(['035', '010'], true).each {|f| puts f.to_s}
310
+ # # 010 $a 68027371
311
+ # # 035 $a (RLIN)MIUG0001728-B
312
+ # # 035 $a (CaOTULAS)159818044
313
+ # # 035 $a (OCoLC)ocm00001728
314
+
315
+ def find_by_tag(tags, originalorder = false)
316
+ self.hashify unless @hashedtags and !originalorder
317
+ if !tags.is_a? Array
318
+ return @hashedtags[tags] || []
319
+ end
320
+ if originalorder
321
+ return self.find_all {|f| tags.include? f.tag}
322
+ else
323
+ # puts "Tags is #{tags}: got #{@hashedtags.values_at(*tags)}"
324
+ return @hashedtags.values_at(*tags).flatten.compact
325
+ end
326
+ end
327
+
328
+
329
+
330
+ # Return the record as valid MARC-XML
331
+ # @return String A MARC-XML representation of the record, including the XML header
332
+ def to_xml
333
+ return @xml if @xml
334
+ begin
335
+ @xml = java.io.StringWriter.new
336
+ res = javax.xml.transform.stream.StreamResult.new(@xml)
337
+ writer = org.marc4j.MarcXmlWriter.new(res)
338
+ writer.write(self)
339
+ writer.writeEndDocument
340
+ return @xml.toString
341
+ rescue
342
+ "Woops! to_xml failed for record #{self['001'].data}: #{$!}"
343
+ end
344
+ end
345
+
346
+ def to_marc
347
+ begin
348
+ s = Java::java.io.ByteArrayOutputStream.new
349
+ writer = org.marc4j.MarcStreamWriter.new(s)
350
+ writer.write(self)
351
+ @marcbinary = s.to_string
352
+ puts @marcbinary
353
+ return @marcbinary
354
+ rescue
355
+ # "Woops! to_marc failed for record #{self['001'].data}: #{$!}"
356
+ "Whoops! Failed: #{$!}"
357
+ end
358
+ end
359
+
360
+
361
+ end
362
+
363
+ class ControlField
364
+ def value
365
+ return self.data
366
+ end
367
+
368
+ def controlField?
369
+ return true
370
+ end
371
+
372
+ def self.control_tag? tag
373
+ return Java::org.marc4j.marc.impl.Verifier.isControlField tag
374
+ end
375
+
376
+ # Pretty-print
377
+ # @param [String] joiner What string to use to join the subfields
378
+ # @param [String] The pretty string
379
+ def to_s
380
+ return self.tag + " " + self.value
381
+ end
382
+
383
+ def == other
384
+ self.tag == other.tag && self.value == other.value
385
+ end
386
+
387
+ end
388
+
389
+ class DataField
390
+ include Enumerable
391
+
392
+ alias_method :<<, :addSubfield
393
+
394
+
395
+ def controlField?
396
+ return false
397
+ end
398
+
399
+ # Broken. Need to check subs as well
400
+ def == other
401
+ self.tag == other.tag and
402
+ self.indicator1 == other.indicator1 and
403
+ self.indicator2 == other.indicator2
404
+ end
405
+
406
+ # Pretty-print
407
+ # @param [String] joiner What string to use to join the subfields
408
+ # @param [String] The pretty string
409
+ def to_s (joiner = ' ')
410
+ arr = [self.tag + ' ' + self.indicator1 + self.indicator2]
411
+ self.each do |s|
412
+ arr.push s.to_s
413
+ end
414
+ return arr.join(joiner)
415
+ end
416
+
417
+ # Get the value of the first subfield of this field with the given code
418
+ # @param [String] code 1-character string of the subfield code
419
+ # @return [String] The value of the first matched subfield
420
+ def [] code
421
+ raise ArgumentError, "Code must be a one-character string, not #{code}" unless code.is_a? String and code.size == 1
422
+ # need to send a char value that the underlying java can deal with
423
+ sub = self.getSubfield(code[0].ord)
424
+ if (sub)
425
+ return sub.getData
426
+ else
427
+ return nil
428
+ end
429
+ end
430
+
431
+
432
+ # Get all values from the subfields for the given code or array of codes
433
+ # @param [String, Array<String>] code (Array of?) 1-character string(s) of the subfield code
434
+ # @param [Boolean] myorder Use the order of subfields that I gave instead of the order they're in the record
435
+ # @return [Array<String>] A possibly-empty array of Strings made up of the values in the subfields whose
436
+ # code is included in the given codes. If myorder == true, use the order in which they are passed in; if a code is repeated
437
+ # (ocassionally legal) subfield values will appear first ordered by the passed array, then by order within
438
+ # the document.
439
+ #
440
+ # If myorder is false, just return the values for matching subfields in the order they appear in the field.
441
+ #
442
+ # @example Quick examples:
443
+ # # 260 $a New York, $b Van Nostrand Reinhold Co. $c 1969
444
+ # rec['260'].sub_values('a') #=> ["New York,"]
445
+ # rec['260'].sub_values(['a', 'c']) #=> ["New York,", "1969"]
446
+ # rec['260'].sub_values(['c', 'a']) #=> ["New York,", "1969"]
447
+ # rec['260'].sub_values(['c', 'a'], true) #=> ["1969", "New York"]
448
+
449
+ def sub_values(code, myorder = false)
450
+
451
+ # Do a little razzle-dazzle for the common case when a single code is given
452
+ if not [Set, Array].include? code.class
453
+ c = code
454
+ elsif code.size == 1
455
+ c = code.first
456
+ end
457
+ if c
458
+ return self.find_all { |s| c == s.code}.map {|s| s.data}
459
+ end
460
+
461
+ # unless [Set, Array].include? code.class
462
+ # code = [code]
463
+ # # puts "Arrayified for code #{code} / #{code.class}"
464
+ # end
465
+ if myorder
466
+ subs = []
467
+ code.each do |c|
468
+ subs << self.find_all {|s| c == s.code}
469
+ end
470
+ return subs.flatten.map {|s| s.data}
471
+ else
472
+ return self.find_all{|s| code.include? s.code}.map {|s| s.data}
473
+ end
474
+ end
475
+
476
+ # Get first indicator as a one-character string
477
+ def indicator1
478
+ return self.getIndicator1.chr
479
+ end
480
+
481
+ # Get second indicator as a one-character string
482
+ def indicator2
483
+ return self.getIndicator2.chr
484
+ end
485
+
486
+ # Iterate over the subfields
487
+ def each
488
+ self.getSubfields.each do |s|
489
+ yield s
490
+ end
491
+ end
492
+
493
+ # Get the concatentated values of the subfields in order the appear in the field
494
+ # @param [String] joiner The string used to join the subfield values
495
+ def value joiner=' '
496
+ data = self.getSubfields.map {|s| s.data}
497
+ return data.join(joiner)
498
+ end
499
+ end
500
+
501
+ class SubField
502
+
503
+ def == other
504
+ return ((self.code == other.code) and (self.data == other.data))
505
+ end
506
+
507
+ def value
508
+ return self.data
509
+ end
510
+
511
+ def code
512
+ return self.getCode.chr
513
+ end
514
+
515
+ def to_s
516
+ return '$' + self.code + " " + self.data
517
+ end
518
+ end
data/spec/batch.dat ADDED
@@ -0,0 +1 @@
1
+ 00755cam 22002414a 4500001001300000003000600013005001700019008004100036010001700077020004300094040001800137042000800155050002600163082001700189100003100206245005400237260004200291300007200333500003300405650003700438630002500475630001300500fol05731351 IMchF20000613133448.0000107s2000 nyua 001 0 eng  a 00020737  a0471383147 (paper/cd-rom : alk. paper) aDLCcDLCdDLC apcc00aQA76.73.P22bM33 200000a005.13/32211 aMartinsson, Tobias,d1976-10aActivePerl with ASP and ADO /cTobias Martinsson. aNew York :bJohn Wiley & Sons,c2000. axxi, 289 p. :bill. ;c23 cm. +e1 computer laser disc (4 3/4 in.) a"Wiley Computer Publishing." 0aPerl (Computer program language)00aActive server pages.00aActiveX.00647pam 2200241 a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001500161100002600176245006700202260003800269263000900307300001100316650003700327650002500364700001600389fol05754809 IMchF20000601115601.0000203s2000 mau 001 0 eng  a 00022023  a1565926994 aDLCcDLCdDLC apcc00aQA76.73.P22bD47 200000a005.742211 aDescartes, Alligator.10aProgramming the Perl DBI /cAlligator Descartes and Tim Bunce. aCmabridge, MA :bO'Reilly,c2000. a1111 ap. cm. 0aPerl (Computer program language) 0aDatabase management.1 aBunce, Tim.00605cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077040001800094042000800112050002700120082001700147100002100164245005500185260004500240300002600285504005100311650003700362fol05843555 IMchF20000525142739.0000318s1999 cau b 001 0 eng  a 00501349  aDLCcDLCdDLC apcc00aQA76.73.P22bB763 199900a005.13/32211 aBrown, Martin C.10aPerl :bprogrammer's reference /cMartin C. Brown. aBerkeley :bOsborne/McGraw-Hill,cc1999. axix, 380 p. ;c22 cm. aIncludes bibliographical references and index. 0aPerl (Computer program language)00579cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002700135082001700162100002100179245005500200260004500255300003600300650003700336fol05843579 IMchF20000525142716.0000318s1999 caua 001 0 eng  a 00502116  a0072120002 aDLCcDLCdDLC apcc00aQA76.73.P22bB762 199900a005.13/32211 aBrown, Martin C.10aPerl :bthe complete reference /cMartin C. Brown. aBerkeley :bOsborne/McGraw-Hill,cc1999. axxxv, 1179 p. :bill. ;c24 cm. 0aPerl (Computer program language)00801nam 22002778a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001800156100002000174245008800194250003200282260004100314263000900355300001100364650003700375650003600412650002600448700002500474700002400499fol05848297 IMchF20000524125727.0000518s2000 mau 001 0 eng  a 00041664  a1565924193 aDLCcDLC apcc00aQA76.73.P22bG84 200000a005.2/7622211 aGuelich, Scott.10aCGI programming with Perl /cScott Guelich, Shishir Gundavaram & Gunther Birznieks. a2nd ed., expanded & updated aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language) 0aCGI (Computer network protocol) 0aInternet programming.1 aGundavaram, Shishir.1 aBirznieks, Gunther.00665nam 22002298a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002700130082001700157111005200174245008600226250001200312260004100324263000900365300001100374650005000385fol05865950 IMchF20000615103017.0000612s2000 mau 100 0 eng  a 00055759  a0596000138 aDLCcDLC apcc00aQA76.73.P22bP475 200000a005.13/32212 aPerl Conference 4.0d(2000 :cMonterey, Calif.)10aProceedings of the Perl Conference 4.0 :bJuly 17-20, 2000, Monterey, California. a1st ed. aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language)vCongresses.00579nam 22002178a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100002800173245006200201260004100263263000900304300001100313650003700324fol05865956 IMchF20000615102948.0000612s2000 mau 000 0 eng  a 00055770  a1565926099 aDLCcDLC apcc00aQA76.73.P22bB43 200000a005.13/32211 aBlank-Edelman, David N.10aPerl for system administration /cDavid N. Blank-Edelman. aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language)00661nam 22002538a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100001700173245006700190250001200257260004100269263000900310300001100319650003700330700002300367700001700390fol05865967 IMchF20000615102611.0000614s2000 mau 000 0 eng  a 00055799  a0596000278 aDLCcDLC apcc00aQA76.73.P22bW35 200000a005.13/32211 aWall, Larry.10aProgramming Perl /cLarry Wall, Tom Christiansen & Jon Orwant. a3rd ed. aCambridge, Mass. :bO'Reilly,c2000. a0007 ap. cm. 0aPerl (Computer program language)1 aChristiansen, Tom.1 aOrwant, Jon.00603cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001700161100003200178245006000210260005700270300003300327650003700360fol05872355 IMchF20000706095105.0000315s1999 njua 001 0 eng  a 00500678  a013020868X aDLCcDLCdDLC apcc00aQA76.73.P22bL69 199900a005.13/32211 aLowe, Vincentq(Vincent D.)10aPerl programmer's interactive workbook /cVincent Lowe. aUpper Saddle River, NJ :bPrentice Hall PTP,cc1999. axx, 633 p. :bill. ;c23 cm. 0aPerl (Computer program language)00696nam 22002538a 4500001001300000003000600013005001700019008004100036010001700077020002800094040001300122042000800135050002600143082001700169100002600186245004400212260005100256263000900307300001100316500002000327650003700347650001700384650004100401fol05882032 IMchF20000707091904.0000630s2000 cau 001 0 eng  a 00058174  a0764547291 (alk. paper) aDLCcDLC apcc00aQA76.73.P22bF64 200000a005.13/32212 aFoster-Johnson, Eric.10aCross-platform Perl /cEric F. Johnson. aFoster City, CA :bIDG Books Worldwide,c2000. a0009 ap. cm. aIncludes index. 0aPerl (Computer program language) 0aWeb servers. 0aCross-platform software development.