Skip to content

Commit

Permalink
cut: fix substring for -b flag (#595)
Browse files Browse the repository at this point in the history
* The substring length calculation in handle_b() wasn't correct in all cases
* If start==end, then length==1
* Pass parameters to handle_b() and handle_f()
* Use defined() to test for presence of command options; 0 should not be ignored
* test1: "perl cut -b 2-3 a.c" -> chars 2-3
* test2: "perl cut -b -3 a.c" -> chars 1-3
* test3: "perl cut -b 10 a.c" -> char 10
* test4: "perl cut -f 1,2 -s  -d ' ' a.c" -> fields 1&2, delimited by space, ignoring lines without a space
  • Loading branch information
mknos committed May 3, 2024
1 parent f3af515 commit cdaeb1d
Showing 1 changed file with 25 additions and 20 deletions.
45 changes: 25 additions & 20 deletions bin/cut
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,18 @@ getopts('b:c:d:f:ns', \%opt) or usage();

# There's no difference between -b and -c on any unix I
# use regularly -- it's for i18n. Thus, -n is a noop, too.
if ($opt{'b'} || $opt{'c'}) {
if (defined $opt{'b'}) {
usage() if $opt{'f'};
handle_b();
} elsif ($opt{'f'}) {
handle_f();
} else {
handle_b($opt{'b'});
}
elsif (defined $opt{'c'}) {
usage() if $opt{'f'};
handle_b($opt{'c'});
}
elsif (defined $opt{'f'}) {
handle_f($opt{'f'}, $opt{'d'}, $opt{'s'});
}
else {
warn "$me: byte, character or field list required\n";
usage();
}
Expand All @@ -50,7 +56,8 @@ sub checknum {
}

sub handle_b {
my @list = split (/,/, $opt{b});
my $spec = shift;
my @list = split /,/, $spec;

while (<>) {
chomp;
Expand All @@ -60,39 +67,37 @@ sub handle_b {
if (substr($item, 0, 1) eq '-') {
checknum($item);
$start = 1;
$end = abs($item) + 1;
$end = abs $item;
}
elsif (index($item, '-') == -1) {
checknum($item);
$start = $item;
$end = $start + 1;
$start = $end = $item;
}
else {
($start, $end) = split /\-/, $item;
checknum($start);
checknum($end);
$end++;
if ($start >= $end) {
warn "$me: invalid byte list\n";
exit EX_FAILURE;
}
}

# change cut's list parameters to substr's parameters
$start = length if $start > length;
$end = length if $end > length;

printf "%s", substr($_, $start - 1, $end - $start);
printf "%s", substr($_, $start - 1, $end - $start + 1);
}
print "\n";
}
}

sub handle_f {
my @list = split (/,/, $opt{f});
my $delim = "\t";
$delim = substr ($opt{d}, 0, 1) if defined $opt{d};
my ($spec, $delim, $sflag) = @_;

my @list = split /,/, $spec;
if (defined $delim) {
$delim = substr $delim, 0, 1;
}
else {
$delim = "\t";
}
while (<>) {
chomp;

Expand Down Expand Up @@ -143,7 +148,7 @@ sub handle_f {
}
}
else { # no delimiter in line
print "$_\n" unless $opt{"s"};
print "$_\n" unless $sflag;
}
}
}
Expand Down

0 comments on commit cdaeb1d

Please sign in to comment.