bob@dhw68k.cts.com (Bob Best) (07/23/88)
Larry Wall took my original cut(1) for perl, and crafted it into a
fast and fancy utility. This little piece of code displays some of the
power and ease of programming in perl. By using the -v (verify) option,
rather than executing the cut, a perl script to perform the task will be
generated and displayed on standard output. The generated script can
then be executed or tailored to suit a more specialized function.
To speed up character list extraction, I added substr() operator support.
See the cut(1) man page for other options.
----------------cut here----------------
#!/usr/bin/perl
#
# cut.pl
# perl version of cut(1)
#
# written by Bob Best (bob@dhw68k.cts.com)
# Larry Wall (lwall@jpl-devvax.jpl.nasa.gov)
#
# Fri Jul 22 20:45:10 PDT 1988
#
# to use space character as delimiter, backslash single quotes (-d\' \')
#
# unlike cut(1), this script lists fields in the specified order
#
# maximum line length for character list extraction can be adjusted
# via '$MAXCHAR' - default is 1024
#
# option '-v' (verify) displays the generated perl script on stdout
#
# see cut(1) man page for other options
#
eval "exec /usr/bin/perl -S $0 $*"
if $running_under_some_shell;
$MAXCHAR=1024;
$delim = "\t";
while ($_ = $ARGV[0], /^-/) {
shift;
/^-c(.*)/ && ($clist=$1) && next;
/^-f(.*)/ && ($flist=$1) && next;
/^-d(.)/ && ($delim=$1) && next;
/^-s/ && ($suppress=1) && next;
/^-v/ && ($verify=1);
}
if (!$clist && !$flist) {die "must specify either -c or -f\n";}
if ($clist && $flist) {die "specify -c or -f but not both\n";}
if ($flist) {$_=$flist;} else {$_=$clist;}
s/(\d*)-(\d*)/do range($1,$2)/eg;
@list=split(/,/);
$[=1;
$init =
'$[=1;
$\ = "\n";
';
$init .=
"\$, = '$delim';
" if $flist;
if ($flist) {
$sdelim = $delim;
$sdelim = '\\' . $sdelim if index('[()?*+$|\\', $delim) >= $[;
$split = "split(/$sdelim/)";
$print = '(print), ' unless $suppress;
}
$printlist = "print ";
if ($flist) {
if ($toend) {
$toend = "
\$end = '';
for (\$i = $toend; \$i <= \$maxfld; ++\$i) {
\$end .= \$_[\$i];
\$end .= '$delim';
}
chop(\$end);";
foreach $i (@list) {
if ($i eq 'MAX') {
$printlist .= "\$end, ";
}
else {
$printlist .= "\$_[$i], ";
}
}
$split = "(@_ = $split)";
}
else { #not toend
$max = 0;
foreach $i (@list) {
$printlist .= "\$Fld$i, ";
$max = $i if $max < $i;
}
$splitlist = '';
for ($i = 1; $i <= $max; ++$i) {
$splitlist .= "\$Fld$i, ";
}
$splitlist =~ s/, $//;
$split = "(($splitlist) = $split)";
}
}
if ($clist) {
$j=1;
foreach $i (@list) {
if ($i == '-') { #range
$ptr=$offsets[$j];
$cnt=$lengths[$j++];
$printlist .= "substr(\$_,$ptr,$cnt), ";
}
else { #char
$printlist .= "substr(\$_,$i,1), ";
}
}
}
$printlist =~ s/, $/;\n/;
if ($flist) { #flist
$loop = "
$init
line: while (<>) {
chop;
\$maxfld = $split;
${print}next line if \$maxfld == 1;
$toend
$printlist
}
";
}
else { #clist
$loop =
"$init
while (<>) {
chop;
$printlist
}
";
}
if ($verify) {
print $loop;
}
else {
eval $loop;
}
sub range {
local($min,$max) = @_;
$min = 1 unless $min;
if (!$max) {
if ($flist) {
$toend = $min;
return 'MAX';
}
else {
$max=$MAXCHAR;
}
}
if ($clist) {
$offsets[$rangecnt]=$min;
$lengths[$rangecnt++]=$max-$min+1;
}
else { #flist
for ($i=$min+1; $i<=$max; ++$i) {
$min .= ",$i";
}
}
$flist ? return $min : return '-';
}
--
Bob Best
uucp: ...{trwrb,hplabs}!felix!dhw68k!bob InterNet: bob@dhw68k.cts.com