DBROWEVAL(1)

πŸ“¦
version 3.9 Β· 3 versions
, in epel 9

πŸ’… dbroweval β€” the "do something to every row" bestie

okay so real talk: this is dbroweval, one of the Perl-flavored Fsdb tools (you'll see it filed under "User Contributed Perl Documentation"). It's the one that runs a lil snippet of code on every single row of your fsdb file. Basically awk energy, but make it fsdb. ✨


🌸 NAME 🌸

dbroweval β€” evaluate code for each row of a fsdb file

πŸŽ€ SYNOPSIS πŸŽ€

    dbroweval [-f CodeFile] code [code...]

πŸ’– DESCRIPTION πŸ’–

So what it does: it evaluates your code for each row of the data. That's it, that's the vibe.

The classic use case is stuff like reformatting and other data transformations β€” glow-ups for your rows, basically.

Here's the fun part πŸ‘‘: your code can include embedded column names, and you write them with an underscore in front. When the code runs, that underscore-name gets you the value of that column for the current row. So _mean is the current row's mean. Slay.

And the last row's column values? Those come from _last_foo, where foo is the column name. Yes, we keep receipts on the previous row too πŸ’….

Even more perverse (their word, not mine 😭): _columname(N) gives you the value of the Nth column after columnname β€” so _columnname(0) is also the column's value. (Note the spelling: _columname, with the missing n. That's not me being sloppy, that's literally how it's written. fr fr.)

✨ OPTIONS ✨

  • -b CODE β€” run CODE before reading any data (the awk BEGIN block of your dreams).
  • -e CODE β€” run CODE at the end of all data (hello awk END block 🫢).
  • -f FILE β€” read the code from FILE.
  • -n or --no-output β€” no output except for comments and whatever's in the code you provided.
  • -N or --no-output-even-comments β€” no output at all, except for what's in the provided code. Not even the comments. Zero. Nada. πŸ’€
  • -m or --manual-output β€” you, the user, must set up the output yourself, which lets you do arbitrary comments. See example 2 below for the deets.
  • -w or --warnings β€” turn on warnings in user supplied code.
  • --saveoutput $OUT_REF β€” save the output writer (for integration with other fsdb filters).

This module also supports the standard fsdb options, bestie:

  • -d β€” enable debugging output.
  • -i or --input InputSource β€” read from InputSource, which is typically a file name, or - for standard input, or (if you're in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue object.
  • -o or --output OutputDestination β€” write to OutputDestination, typically a file name, or - for standard output, or (if in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue object.
  • --autorun or --noautorun β€” by default programs process automatically, but Fsdb::Filter objects in Perl don't run until you invoke the run() method. The --(no)autorun option controls that behavior within Perl.
  • --header H β€” use H as the full Fsdb header, rather than reading a header from then input. (Yes, "then input". That's the original wording, I don't make the rules πŸ™ˆ)
  • --help β€” show help.
  • --man β€” show full manual.

πŸ¦‹ ADVANCED USAGE πŸ¦‹

Normally dbroweval outputs a line in the same schema for each input line. But for advanced usage, you can violate each of these assumptions. Breaking rules is free, apparently 😌

Some fun:

  • omitting a line β€” add the code next row if ($your condition);
  • outputting an extra line β€” call &$write_fastpath_sub($fref). You may find $fref, the input row, useful.
  • changing the schema β€” see the examples below in "Command 2: Changing the Schema"

🌈 SAMPLE USAGE 🌈

πŸ“ Input:

#fsdb      size    mean    stddev  pct_rsd
1024    1.4962e+06      2.8497e+05      19.047
10240   5.0286e+06      6.0103e+05      11.952
102400  4.9216e+06      3.0939e+05      6.2863
#  | dbsetheader size bw
#  | /home/johnh/BIN/DB/dbmultistats size bw
#  | /home/johnh/BIN/DB/dbcol size mean stddev pct_rsd

🌸 Command:

cat data.fsdb | dbroweval '_mean = sprintf("%8.0f", _mean); _stddev = sprintf("%8.0f", _stddev);'

πŸ’œ Output:

#fsdb      size    mean    stddev  pct_rsd
1024     1496200          284970        19.047
10240    5028600          601030        11.952
102400   4921600          309390        6.2863
#  | dbsetheader size bw
#  | /home/johnh/BIN/DB/dbmultistats size bw
#  | /home/johnh/BIN/DB/dbcol size mean stddev pct_rsd
#  | /home/johnh/BIN/DB/dbroweval   { _mean = sprintf("%8.0f", _mean); _stddev = sprintf("%8.0f", _stddev); }

πŸ‘‘ Command 2: Changing the Schema

By default, dbroweval reads and writes the same format file. The recommended method of adding and removing columns is to do so before or after dbroweval. I.e.,

cat data.fsdb |
    dbcolcreate divisible_by_ten |
    dbroweval '_divisible_by_ten = (_size % 10 == 0);' |
    dbrow '_divisible_by_ten == 1' |
    dbcol size mean divisible_by_ten

Another approach is to use the next row command to skip output of a row. I.e., the equivalent:

cat data.fsdb |
    dbcolcreate divisible_by_ten |
    dbroweval '_divisible_by_ten = (_size % 10 == 0); next row if (!_divisible_by_ten);' |
    dbcol size mean divisible_by_ten

However, neither of these approachs work very well when the output is a completely different schema. (Their spelling of "approachs", not mine 🫢)

The recommended method for schema-changing commands is to write a full filter, but a full filter is a bit heavy weight. As an alternative, one can use the -m option to request manual configuration of the output, then use @out_args to define the output schema (it specifies the Fsdb::IO::Writer arguments), and $ofref is the output row. It may also reference <$in>, the input Fsdb::IO::Reader argument, and <$fref> as an aref to the current line. Note that newly created columns do not have underscore-names.

Thus a third equivalent is:

cat data.fsdb | \
    dbroweval -m -b '@out_args = ( -clone => $in, \
             -cols => ($in->cols, divisible_by_ten); ' \
        'my $div_by_10 = (_size % 10 == 0); \
        $ofref = [ @$fref, $div_by_10 ] if ($div_by_ten);' |
    dbcol size mean divisible_by_ten

or

cat data.fsdb | \
    dbroweval -m -b '@out_args = ( -clone => $in, \
            -cols => [qw(size mean divisible_by_ten)] ); ' \
        'my $div_by_10 = (_size % 10 == 0);  \
        $ofref = [ _mean, _size, $div_by_10 ] if ($div_by_ten);'

Finally, one can write different a completely different schema, although it's more work:

cat data.fsdb | \
    dbroweval -m -b '@out_args = (-cols => [qw(size n)]);' \
        '$ofref = [ _size, 1 ];'

writes different columns, and

cat data.fsdb | \
    dbroweval -n -m -b '@out_args = (-cols => [qw(n)]);  \
        my $count = 0;' -e '$ofref = [ $count ];' '$count++;'

Is a fancy way to count lines. Fancy!! πŸ’…

The begin code block should setup @out_args to be the arguments to a Fsdb::IO::Writer::new call, and whatever is in $ofref (if anything) is written for each input line, and once at the end.

πŸ’€ Command 3: Fun With Suppressing Output

The -n option suppresses default output. Thus, a simple equivalent to tail -1 is:

dbroweval -n -e '$ofref = $lfref;'

Where $ofref is the output fields, which are copied from $lfref, the hereby documented internal representation of the last row. Yes, this is a bit unappetizing, but, in for a penny with $ofref, in for a pound. 😭

πŸŽ€ Command 4: Extra Ouptut

(Yes, "Ouptut". Iconic typo. We keep it. πŸ‘‘)

Calling &$write_fastpath_sub($fref) will do extra output, so this simple program will duplicate each line of input (one extra output, plus one regular output for each line of input):

dbroweval  '&$write_fastpath_sub($fref)'

πŸ™ˆ BUGS πŸ™ˆ

Handling of code in files isn't very elegant. That's it. That's the bug report. ngl, relatable.

πŸ”₯ SEE ALSO πŸ”₯

Fsdb(3)

Copyright (C) 1991-2018 by John Heidemann <johnh@isi.edu>

This program is distributed under terms of the GNU general public license, version 2. See the file COPYING with the distribution for details.


okay so that's the whole thing, bestie β€” go forth and row-evaluate 🌟 This page came to you courtesy of perl v5.32.1, dated 2024-08-02, and it's the DBROWEVAL(1) manual page. mwah πŸ’‹

πŸ“¦ where this page comes from