From c69ff84ae66511a1ffa5a5d0b32d554d2f2861ba Mon Sep 17 00:00:00 2001 From: Ole Tange Date: Wed, 3 Jun 2020 20:13:20 +0200 Subject: [PATCH] field: Converted to wrapper for (m)awk. --- Makefile | 13 ++--- field/field | 143 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 127 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 3b1ff0c..e012e58 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,19 @@ CMD = blink 2grep 2search burncpu duplicate-packets em encdir field \ forever fxkill G gitnext gitundo goodpasswd histogram mtrr \ - mirrorpdf neno off parsort pdfman pidcmd plotpipe puniq \ - ramusage rand rclean rina rn rrm seekmaniac shython \ + mirrorpdf neno off parsort pdfman pidcmd pidtree plotpipe \ + puniq ramusage rand rclean rina rn rrm seekmaniac shython \ sound-reload splitvideo stdout swapout T timestamp tracefile \ transpose upsidedown vid w4it-for-port-open whitehash \ wifi-reload wssh ytv yyyymmdd all: blink/blink.1 2search/2grep.1 2search/2search.1 \ - burncpu/burncpu.1 encdir/encdir.1 G/G.1 gitnext/gitnext.1 \ - gitundo/gitundo.1 goodpasswd/goodpasswd.1 \ + burncpu/burncpu.1 encdir/encdir.1 field/field.1 G/G.1 \ + gitnext/gitnext.1 gitundo/gitundo.1 goodpasswd/goodpasswd.1 \ histogram/histogram.1 mirrorpdf/mirrorpdf.1 neno/neno.1 \ off/off.1 parsort/parsort.1 pdfman/pdfman.1 pidcmd/pidcmd.1 \ - plotpipe/plotpipe.1 puniq/puniq.1 rand/rand.1 rina/rina.1 \ - rn/rn.1 rrm/rrm.1 seekmaniac/seekmaniac.1 shython/shython.1 \ + pidtree/pidtree.1 plotpipe/plotpipe.1 puniq/puniq.1 \ + rand/rand.1 rina/rina.1 rn/rn.1 rrm/rrm.1 \ + seekmaniac/seekmaniac.1 shython/shython.1 \ sound-reload/sound-reload.1 splitvideo/splitvideo.1 \ stdout/stdout.1 timestamp/timestamp.1 tracefile/tracefile.1 \ transpose/transpose.1 T/T.1 upsidedown/upsidedown.1 vid/vid.1 \ diff --git a/field/field b/field/field index 7197efd..3b1b0e9 100755 --- a/field/field +++ b/field/field @@ -1,36 +1,133 @@ -#!/usr/bin/perl -an +#!/usr/bin/perl -# field 1 -# field 3,1 -# field 6,2-3 -# field 6- -# field 2,6-,2-3 +=pod -BEGIN { - @ranges = split(/,/, shift); +=head1 NAME + +field - select fields in tabular files + + +=head1 SYNOPSIS + +B I file + +... | B I + + +=head1 DESCRIPTION + +B selects fields in tabular files. + + +=head1 EXAMPLE + +Select field 2: + + field 2 file + +Select field 2,3,4,5: + + field 2-5 file + +Select field 2..end: + + field 2- file + +Select field 2,3,4,1: + + field 2-4,1 file + + +=head1 AUTHOR + +Copyright (C) 2017-2020 Ole Tange, +http://ole.tange.dk and Free Software Foundation, Inc. + + +=head1 LICENSE + +Copyright (C) 2012 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +at your option any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +=head1 SEE ALSO + +B + + +=cut + +use strict; + +my @fields = range_to_fields(shift); +my $fields = join(",", @fields); + +sub range_to_fields { + my @ranges = split(/,/, shift); + my @fields; for (@ranges) { /^(\d+)$/ and push (@fields,($1-1)); /^(\d+)-(\d+)$/ and push (@fields,($1-1) .. ($2-1)); /^(\d+)-$/ and do { push (@fields,($1-1)." .. \$#F"); - $must_eval = 1; + $Global::must_eval = 1; }; } # Default: field 1 - if(not @fields) { @fields=(1-1); } # Perl counts from 0 - not from 1 - $fields = join(",", @fields); -} -if($must_eval) { - if(not $Calc::f{$#F}) { - # Eval is expensive, so only do it if we have not done before - # If an argument ends in '-' then we must figure out the last field - # which depends on the number of fields in the line - $Calc::f{$#F}++; - @{$Calc::fields->{$#F}} = eval $fields; - } - print join(" ",@F[@{$Calc::fields->{$#F}}]),"\n"; -} else { - print join(" ",@F[@fields]),"\n"; + if(not @fields) { @fields=(1-1); } + return @fields; } +if($Global::must_eval) { + while(<>) { + my @F = split/\s+/,$_; + if(not $Calc::f{$#F}) { + # Eval is expensive, so only do it if we have not done before + # If an argument ends in '-' then we must figure out the last field + # which depends on the number of fields in the line + $Calc::f{$#F}++; + @{$Calc::fields->{$#F}} = eval $fields; + } + print join(" ",@F[@{$Calc::fields->{$#F}}]),"\n"; + } +} else { + # awk counts from 1 not 0 + @fields = map { $_+1 } @fields; + # Use mawk (60 MB/s)/gawk (30 MB/s)/awk (? MB/s) + my $awk = which("mawk") || which("gawk") || which("awk"); + + my $awkscript = '{print '. + (join ",", map { '$'.$_ } @fields). + '}'; + exec($awk,$awkscript); +} + +sub which { + # Input: + # @programs = programs to find the path to + # Returns: + # @full_path = full paths to @programs. Nothing if not found + my @which; + for my $prg (@_) { + push(@which, grep { not -d $_ and -x $_ } + map { $_."/".$prg } split(":",$ENV{'PATH'})); + if($prg =~ m:/:) { + # Including path + push(@which, grep { not -d $_ and -x $_ } $prg); + } + } + return wantarray ? @which : $which[0]; +}