7 td-alter - Add new columns and fields to tabular data stream, and modify value of existing fields.
11 td-alter I<COLUMN>=I<EXPR> [I<COLUMN>=I<EXPR> [I<COLUMN>=I<EXPR> [...]]]
15 On each data row, sets field in I<COLUMN> to the value resulted by I<EXPR>
18 In I<EXPR>, you may refer to other fields by C<$F{NAME}> where I<NAME> is the column name;
19 or by C<$F[INDEX]> where I<INDEX> is the 0-based column index number.
20 Furthermore you may refer to uppercase alpha-numeric field names, simply by bareword C<COLUMN>,
21 well, enclosed in paretheses like C<(COLUMN)> to avoid parsing unambiguity in Perl.
22 It's possible because these column names are set up as subroutines internally.
24 Topic variable (C<$_>) initially is set to the current value of I<COLUMN> in I<EXPR>.
25 So for example C<N='-$_'> makes the field N the negative of itself.
27 You can create new columns simply by referring to a I<COLUMN> name that does not exist yet.
28 You can refer to an earlier defined I<COLUMN> in subsequent I<EXPR> expressions.
32 Add new columns: TYPE and IS_BIGFILE.
33 IS_BIGFILE depends on previously defined TYPE field.
35 ls -l | td-trans-ls | td-alter TYPE='substr MODE,0,1' IS_BIGFILE='SIZE>10000000 && TYPE ne "d" ? "yes" : "no"'
37 Strip sub-seconds and timezone from DATETIME field:
39 TIME_STYLE=full-iso ls -l | td-trans-ls | td-alter DATETIME='s/\..*//; $_'
45 =item -H, --no--header
51 show headers (default)
57 "Alter" in td-alter comes from SQL.
58 td-alter(1) can change the "table" column layout.
59 But contrary to SQL's ALTER TABLE, td-alter(1) can modify the records too, so akin to SQL UPDATE as well.
65 'H|no-header' => sub { $OptShowHeader = 0; },
66 'h|header' => sub { $OptShowHeader = 1; },
69 no if ($] >= 5.018), 'warnings' => 'experimental::smartmatch';
70 do '/usr/lib/tool/perl5/tabdata/common.pl' or die "$@";
72 process_header
(scalar <STDIN
>);
78 if($ARGV[0] =~ /^([^=]+)=(.*)/)
83 if(not exists $Header{$column})
85 push @Header, $column;
86 $Header{$column} = $#Header;
89 push @Derives, {'column'=>$column, 'expr'=>$expr};
93 pod2usage
(-exitval
=>2, -verbose
=>99, -msg
=>"$0: unknown parameter: $ARGV[0]");
98 if($OptShowHeader and @Header)
100 print join($FS, @Header).$RS;
103 while($line = <STDIN
>)
107 @F = split $FS, $line;
108 %F = map {$_=>$F[$Header{$_}]} keys %Header;
112 my $cidx = $Header{$d->{'column'}};
113 my $expr_prerun = '';
114 for my $col (grep {/^[A-Z_][A-Z0-9_]*$/} @Header)
116 # define all (uppercase alpha-numeric only) column name as a subroutine
117 # which return the given field's value.
118 $expr_prerun .= sprintf('sub %s { $F{"%s"} };', $col, $col);
120 $expr_prerun .= '$_ = $F[$cidx];';
121 my $expr = $expr_prerun . $d->{'expr'};
123 $F[$cidx] = $F{$d->{'column'}} = eval $expr;
127 # undefined is empty string in tab-data format.
130 $F[$idx] = '' if not defined $F[$idx];
133 print join($FS, @F).$RS;