MARC::Loop(3pm)

πŸ’– MARC::Loop β€” process a batch of MARC21 records πŸ’–

hiii bestie 🫢 okay so this is the MARC::Loop(3pm) page, straight out of the User Contributed Perl Documentation, and I am so excited to walk you through it. it's giving "bare-bones procedural Perl that absolutely ate". let's go πŸ’…


🌸 NAME 🌸

MARC::Loop β€” process a batch of MARC21 records ✨


✨ SYNOPSIS ✨

okay so here's the whole vibe, look at her go:

use MARC::Loop qw(marcloop marcbuild TAG VALREF DEL);
my $filehandle = \*STDIN;
my $deleted999 = 0;
my $fixed035 = 0;
marcloop {
    my ($leader, $fields, $raw_marc_ref) = @_;
    my $changed;
    foreach my $field (@$fields) {
        if ($field->[TAG] eq '035') {
            # Normalize OCLC numbers
            my $valref = $field->[VALREF];
            $$valref =~ s/\(OCoLC\)oc[mn]0*/(OCoLC)/g;
            $fixed035++;
            $changed = 1;
        }
        elsif ($field->[TAG] eq '999') {
            # Delete 999 fields
            $field->[DEL] = 1;
            $deleted999++;
            $changed = 1;
        }
    }
    # Print only changed records
    print marcbuild($leader, $fields) if $changed;
} $filehandle;
print STDERR "$deleted999 999 fields were deleted\n",
             "$fixed035 035 fields were fixed\n";

so you pull in marcloop, marcbuild, and the lil constants TAG, VALREF, DEL. you point $filehandle at \*STDIN, you zero out your two counters, and then you hand marcloop a block that goes through every field, normalizes the 035 OCLC numbers, flags every 999 for deletion with $field->[DEL] = 1, and only prints the records that actually changed. then it spills the receipts to STDERR. iconic behaviour honestly. πŸ‘‘


πŸ¦‹ DESCRIPTION πŸ¦‹

MARC::Loop is an alternative to MARC::File and MARC::Record that eschews an object-oriented approach in favor of a bare-bones procedural one.

and that's the whole pitch bestie β€” no objects, no ceremony, just functions and data structures. lowkey refreshing. 🌈


πŸ’œ FUNCTIONS πŸ’œ

All of these functions are exported upon request.

iykyk: nothing shows up in your namespace unless you ask for it in the use line. shy but generous. πŸŽ€

🌟 marcloop 🌟

# This example prints a MARC record in human-readable form, using a single
# line for each field no matter how many subfields it might have.
use MARC::Loop qw(marcloop);
marcloop {
    my ($leader, $fields, $raw_marc_ref) = @_;
    foreach my $field (@$fields) {
        if ($field->[TAG] lt '010) {
            # Control field
            my $valref = $field->[VALREF];
            print $field->[TAG], '    ', $$valref, "\n";
        }
        else {
            # Data field
            my ($i1, $i2) = ($field->[IND1], $field->[IND2]);
            print "$field->[TAG] $i1$i2";
            my @subfields  = @{ $field->[SUBS..$#$field] };
            foreach my $subfield (@subfields) {
                my ($code, $valref) = @$subfield;
                print '$', $code, ' ', $$valref;
            }
            print "\n";
        }
    }
} $filehandle, %options;

this one prints a MARC record in human-readable form, one single line per field no matter how many subfields it's carrying. πŸ’–

Options:

  • print_all β€” All MARC records will be printed to STDOUT. Any changes you make will be reflected in what is printed.
  • drop array_ref β€” Tags of fields to be dropped unconditionally.
'drop' => [ '001', '090' ]
  • only array_ref β€” Tags of fields to be preserved; all other fields will be dropped. (The leader is never dropped, of course.)
'only' => [ qw(001 004 008 852 856) ]
  • error β€” A code reference to call when there is an error.
'error' => sub { exit -1 }
  • strict β€” Halt processing when an ill-formed MARC record is encountered.
'strict' => 1

Options will be more fully documented in a future release; in the meantime, read the source code.

not me telling you to go read the source 😭 but fr fr, that's what the page says. go read the source.

🌟 marcparse 🌟

($leader, $fields) = marcparse(\$string, %options);

Parses a MARC record into the same data structure that marcloop uses. Options are mostly the same as for marcloop.


🌟 marcbuild 🌟

print marcbuild($leader, $fields);

Builds a raw MARC record from the same data structure that marcloop uses and that marcparse produces.


🌟 marcfield 🌟

# Control field
push $@fields, marcfield(
    '001',   # Tag
    1234567, # Content
);

# Data field
push $@fields, marcfield(
    '245',              # Tag
    ' ', ' ',           # Indicators
    'a' => 'Blah blah', # Subfield $a
    'c' => 'Amy Emu',   # Subfield $c
    ...                 # More subfields
);

A convenience function to build a data structure representing a single MARC21 field.

she's a lil helper and she's doing her best 🧚


πŸ’€ BUGS πŸ’€

The documentation is woefully lacking and probably just plain wrong. Read the source code β€” or, better yet, step through it in the Perl debugger β€” to get a better understanding of what this code does.

Unhandled errors cause ill-formed records to be dropped without notice. You must specify an error option to marcloop to get around this.

okay bestie this one is a REAL warning, not a vibe check: ill-formed records get dropped without notice if you don't hand marcloop an error option. πŸ™ˆ do not skip this. your data will simply vanish and nobody will text you about it.

πŸ‘‘ AUTHOR πŸ‘‘

Paul Hoffman <paul@flo.org>.


Copyright 2009-2010 Fenway Libraries Online. Released under the GNU General Public License, version 3.


and that's the page, bestie!! πŸŽ€ this was MARC::Loop(3pm), perl v5.36.0, dated 2023-01-27 β€” shoutout to the version and the date for holding it down at the bottom of every manpage ever. go forth and loop those records, you absolute main character πŸ’–βœ¨πŸ¦‹