{"id":17136,"date":"2022-02-25T14:14:00","date_gmt":"2022-02-25T13:14:00","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/"},"modified":"2025-10-24T09:38:37","modified_gmt":"2025-10-24T07:38:37","slug":"dctmapi-awk-revisited-part-ii","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/","title":{"rendered":"DctmAPI.awk revisited (part II)"},"content":{"rendered":"<p>This is part II of the article <em>DctmAPI.awk revisited<\/em>. See <a href=\"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-i\" target=\"_blank\" rel=\"noopener\">Part I<\/a> here.<br \/>\nThe table presentation can be visually quite rich: it supports row colorization with optional color alternation and gridding, i.e. enclosing the table and data into a grid.<br \/>\nRow colorization allows to colorize the data with a foreground color and an optional background color without alternation, e.g. with a yellow foreground and the default (black) background:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-noback-2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-noback-2.png\" alt=\"\" width=\"300\" height=\"104\" class=\"alignnone size-medium wp-image-54612\" \/><\/a><br \/>\nOr with a background, e.g. white on magenta:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_white-magenta_1.0-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_white-magenta_1.0-1.png\" alt=\"\" width=\"300\" height=\"85\" class=\"alignnone size-medium wp-image-54608\" \/><\/a><br \/>\nColors are specified through the syntax:<br \/>\n<code><br \/>\n[-]fg[.[-]bg]<br \/>\n<\/code><br \/>\nwhere <em>bg<\/em> is optional, <em>fg<\/em> and <em>bg<\/em> can optionally have a leading minus sign and are one of the following colors:<br \/>\n<code><br \/>\nblack, red, green, yellow, blue, magenta, cyan, white, BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, reset<br \/>\n<\/code><br \/>\nLowercase letters are used for normal\/dim intensity and uppercase ones for bright intensity, a convenient notation we shamelessly stole from the <em>rlwrap<\/em> utility (see <a href=\"https:\/\/www.dbi-services.com\/blog\/enhancing-idql-iapi-with-rlwrap-part-i\/\" target=\"_blank\" rel=\"noopener\">Enhancing idql\/iapi with rlwrap (parts I &amp; II)<\/a>).<br \/>\nThe special color <em>reset<\/em> means to use the terminal&#8217;s default color for the given position, either foreground or background.<br \/>\nA minus sign disables the colorization (i.e. use the terminal&#8217;s default) in the respective position. As expected, when both foreground and background colors are negative, no colorization takes place.<br \/>\nColors use ANSI sequences as presented in <a href=\"https:\/\/en.wikipedia.org\/wiki\/ANSI_escape_code\">ANSI escape code<\/a>.<br \/>\nThe interface&#8217;s <em>init_colors()<\/em> initializes the global associative arrays <em>FG_COLORS<\/em> and <em>BG_COLORS<\/em> with the ANSI colore code sequences. Those arrays are indexed by the above color names.<br \/>\nThe interface&#8217;s function <em>colorize()<\/em> takes a string and a color with the format <em>fg[.bg]<\/em> and outputs the string bracketed with the corresponding color&#8217;s ANSI sequence.<br \/>\nThe demo program <em>tdctm.awk<\/em> includes 2 functions to show how the colors look like on the current terminal, <em>test_colors_8bits()<\/em> and <em>test_colors()<\/em>. For one, <em>xterm<\/em> renders them particularly well, brightly and very distinctively. Result may vary widely across the numerous terminal emulators on Linux.<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/supported_colors-3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/supported_colors-3.png\" alt=\"\" width=\"300\" height=\"107\" class=\"alignnone size-medium wp-image-54609\" \/><\/a><br \/>\nUsually, modern terminals support 8-bit foreground and background colors, e.g.:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/8bit_colors.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/8bit_colors.png\" alt=\"\" width=\"300\" height=\"80\" class=\"alignnone size-medium wp-image-54601\" \/><\/a><br \/>\nHowever, to simplify the interface, only the above color names are supported. Although fun, it doesn&#8217;t make much sense here to choose a color among its 256 shades.<br \/>\nAn optional color alternation period can be specified through the following regular expression:<br \/>\n<code><br \/>\n[-]{0-9}[.[-]{0-9}]<br \/>\n<\/code><br \/>\nThe first group of digits expresses for how many lines the specified foregound\/background color should be used before being possibly reversed to background\/foregound. If negative, foreground color is disabled and defaults to the terminal&#8217;s current default (white).<br \/>\nThe second group, optional, expresses for how many lines the specified background\/foregound color should be used. If negative, background color is disabled and defaults to the terminal&#8217;s current default (black).<br \/>\nFor example, we can request that the rows be displayed in yellow foreground and red background, and that this pattern be reversed every 3 lines, i.e 3 lines of yellow\/red followed by 3 lines of red\/yellow (set <em>colors<\/em> to the string &#8220;yellow.red&#8221; and <em>col_periods<\/em> to the string &#8220;3.3&#8221;).<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-red_3-3-2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-red_3-3-2.png\" alt=\"\" width=\"2511\" height=\"344\" class=\"alignnone size-full wp-image-54621\" \/><\/a><br \/>\nSame using BRIGHT colors:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_YELLOW-RED_3-3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_YELLOW-RED_3-3.png\" alt=\"\" width=\"300\" height=\"93\" class=\"alignnone size-medium wp-image-54592\" \/><\/a><br \/>\nThe 2 first lines could be printed in blue\/green and the next 5 lines in green\/blue (set <em>colors<\/em> to the string &#8220;blue.green&#8221; and <em>col_periods<\/em> to the string &#8220;2.5&#8221;).<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_blue-green_2-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_blue-green_2-5.png\" alt=\"\" width=\"300\" height=\"88\" class=\"alignnone size-medium wp-image-54598\" \/><\/a><br \/>\nOr the reverse colors first (set <em>colors<\/em> to the string &#8220;green.blue&#8221;).<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_green-blue_2-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_green-blue_2-5.png\" alt=\"\" width=\"300\" height=\"93\" class=\"alignnone size-medium wp-image-54596\" \/><\/a><br \/>\nOr the first 2 lines in cyan\/white, then the next 4 with the terminal&#8217;s default color (set <em>colors<\/em> to the string &#8220;cyan.white&#8221; and <em>col_periods<\/em> to the string &#8220;2.-4&#8221;).<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_cyan-black_2-4-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_cyan-black_2-4-1.png\" alt=\"\" width=\"300\" height=\"82\" class=\"alignnone size-medium wp-image-54613\" \/><\/a><br \/>\n<em>simple_show_table()<\/em> first prints a line with the column headers. That line is not colorized in order to stand out from the data underneath (just a personal and arbitrary choice, nothing profound herer; it can be changed to something else still personal and arbitrary). If gridding is not wanted, columns are separated by 2 spaces.<br \/>\nThe displayed table can also optionally be enclosed in a grid of various styles, currently 16 of them; here they are:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1; highlight: []\">\n grid_types_str = \"light light-double-dash light-triple-dash light-quadruple-dash heavy heavy-double-dash heavy-triple-dash heavy-quadruple-dash double hdouble-vsingle hsingle-vdouble light-with-round-corners ascii no-grid hheavy-vlight hlight-vheavy half-light\"\n<\/pre>\n<p>Here is how they look like:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/grid-types.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/grid-types.png\" alt=\"\" width=\"300\" height=\"205\" class=\"alignnone size-medium wp-image-54597\" \/><\/a><br \/>\nFunction <em>test_grid()<\/em> in the demo program is invoked to show how they all look like, ranging from no-grid, ascii to the ones drawn with UTF-8 symbols, as most terminals support this standard nowadays. &#8220;ascii&#8221; grid style is the real universal one and doesn&#8217;t look that bad. The fancy UTF-8 ones are nice, although a bit too dense for our taste, even the &#8220;light&#8221; one, but it is a matter of personal preferences.<br \/>\nHere are a few examples of <em>simple_show_table()<\/em> with gridding:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_ascii-grid_yellow-red_3-3-dim.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_ascii-grid_yellow-red_3-3-dim.png\" alt=\"\" width=\"300\" height=\"159\" class=\"alignnone size-medium wp-image-54604\" \/><\/a><br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_light-grid_yellow-reset_2-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_light-grid_yellow-reset_2-5.png\" alt=\"\" width=\"300\" height=\"147\" class=\"alignnone size-medium wp-image-54590\" \/><\/a><br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_double-grid_white-black_2-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_double-grid_white-black_2-5.png\" alt=\"\" width=\"300\" height=\"143\" class=\"alignnone size-medium wp-image-54589\" \/><\/a><br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_light-quadruple-dash-grid_YELLOW-RED_2-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_light-quadruple-dash-grid_YELLOW-RED_2-5.png\" alt=\"\" width=\"300\" height=\"143\" class=\"alignnone size-medium wp-image-54588\" \/><\/a><br \/>\nThe symbols&#8217; UTF-8 codepoints are available from here <a href=\"https:\/\/cloford.com\/resources\/charcodes\/utf-8_box-drawing.htm\">UTF-8 Box Drawing<\/a>. Only the most obvious ones have been used and there are far more possible combinations of symbols to draw even more eye-catching grids, so feel free to experiment and add new grid types to the above list.<br \/>\nThe interface&#8217;s function <em>init_grid_symbols()<\/em> initializes an associative array containing the symbols and is invoked by the aforementioned <em>test_grid()<\/em> and by <em>prep_grid()<\/em>, the latter uses that array to initializes a grid&#8217;s top, middle and bottom lines subsequently used by the functions <em>[simple_]show_table()<\/em>; the former produces the output shown above to help chose a style from.<\/p>\n<p>After the header line come the data. 2 nested loops navigate through the rows and the attributes in <em>result[&#8220;data&#8221;][i][j]<\/em>, plus a third nested loop for multi-valued attributes in <em>result[&#8220;data&#8221;][i][j][k]<\/em>, if any. Before they are printed, the data are optionally enclosed in cells and colorized. Note how the whole colorization logic previously discussed is implemented:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1; highlight: []\">\nprintf(\"%s%-s\", !grid_type || \"no-grid\" == grid_type ? (j &gt; 0 ? \"  \" : \"\") : grid_art[\"ver_line\"], colorize(s, colors &amp;&amp; (i % (nb_fg + nb_bg)) &gt;= nb_fg ? (!bno_inverse ? colors : \"\") : (bno_color ? \"\" : colors), colors &amp;&amp; (i % (nb_fg + nb_bg)) &gt;= nb_fg &amp;&amp; !bno_inverse))\n<\/pre>\n<p>Really terse. This is what happens when one has too many drinks; that logic definitively deserves a better implementation.<\/p>\n<p>As stated, <em>simple_show_table()<\/em> does not limit itself to the screen widths so a lot of wrapping around is expected from the terminal emulator for long lines. In order to still be able to make sense of all the mess on the screen, just pipe the output into the <em>less<\/em> command; use the <em>-S -R<\/em> arguments to prevent wrapping and to correctly interpret the ANSI color codes.<\/p>\n<h3>show_table()<\/h3>\n<pre class=\"brush: bash; gutter: true; first-line: 1; highlight: []\">\n# flexible tabular presentation of the result set in result;\n# title is a string that is printed right before the table, if given;\n# result is the associative array coming from dmSelecta(); see there for a description of its structure;\n# maxw is the default maximum column width, applied to all columns unless it is superseded by requested_max_widths; if -1, requested_max_widths takes over; see below for precedence;\n# if maxw is 0, display_width is used; it is the maximum allowed screen width; if 0, $COLUMNS is used and longer lines get wrapped around by the terminal emulation software; if 0, it is assumed to be unlimited, with possible wrap around;\n# it looks like the environment variable $COLUMNS is not exported so child processes don't see it; <em>gawk<\/em> returns an empty string from ENVIRON[\"COLUMNS\"]; to work around it, just execute an export COLUMNS=$COLUMNS e.g. in a wrapper bash script, before running an awk program that uses DctmAPI;\n# requested_max_widths_str is a comma-separated list of explicitely requested positional column widths, possible empty and\/or with gaps, superseding maxw, e.g. \"10,15,,,8,12,,\" meaning 1st attribute to be displayed in a 10 character wide column, 2nd attribute in a 15 character wide column, 3rd attribute not limited, etc.. ;\n# display_width is the screen width to allocate for the table; must be less or equal to the actual terminal's width to avoid wrapping around by the terminal; if 0, it defaults to the $COLUMNS environment variable;\n# individual column widths are selected in this order of precedence:\n#   maxw &gt; 0, i.e. same width maxw for all the columns;\n#   maxw = 0, display_width &gt; 0: maxw will be set to max(default_min_col, int(screen_width\/length(result[\"medatada\"][\"nb_cols\"]))), with default_min_col = 1;\n#   maxw = 0, display_width = 0: $COLUMNS is taken as display_width, same as above; if not set, maxw is set to the locally declared default_min_col variable;\n#             when display_width is used, available space is allocated to columns as needed; e.g., if an attribute is empty in all the result set, it will receive no additional space; larger attributes will be allocated larger width; the idea is to minimize wrapping or truncation;\n#   maxw = -1: requested_max_widths_str is used if not empty; missing values defaults to their respective result[\"medatada\"][\"max_col_length\"][0...] value;\n#              particular case: empty requested_max_widths_str; max column width defaults to result[\"medatada\"][\"max_col_length\"][0...], i.e. the widest data of the respective column;\n# when result[\"medatada\"][\"max_col_length\"][0...] is used, obviously no truncation nor wrap around take place (except by the terminal) as the respective column widths are large enough for all their data, particularly for their largest datum;\n# wrap_str is string containing a comma-separated list of booleans (value of 0 or 1) indicating if column at respective position has to be wrapped around or not;\n# truncate_str is a string containing a comma-separated list of booleans (value of 0 or 1) indicating if column at respective position has to be truncated or not;\n# wrapping is the default and has priority over truncating;\n#    truncate=0 wrap=0 --&gt; wrapping around;\n#    truncate=0 wrap=1 --&gt; wrapping around;\n#    truncate=1 wrap=0 --&gt; truncate;\n#    truncate=1 wrap=1 --&gt; wrapping around;\n#    truncating is therefore only effective when explicitly and unambiguously requested; this is to preserve data integrity whenever possible;\n# ellipsis string is only considered when truncating and defaults to '...'; thus, by default, there is always one to warn of truncation;\n# that's a lot of fine tuning parameters and at first one may not want to spend time looking for some ideal value; for this reason, it is suggested to start with the following values:\n# thus, a lazy and quick invocation is using the current screen width and possible column wrapping: show_table(title, result)\n# the table will use up to the screen width as needed, with each attribute using up to result[\"medatada\"][\"max_col_length\"][0...] characters, and wrapped around if too large;\n# use an unlimited screen width, no wrapping, best used with | less -S -R: show_table(title, result, -1)\n# further optimization can be done later on as needed;\n# fg_color, bg_color are the respective foreground and background color of the displayed rows;\n# col_periods (format: fg_period . bg_period) are the number of lines to display in the respective color before switching to bg_color\/fg_color for that many lines; i.e. fg_period lines are displayed in fg_color\/bf_color and then bg_period lines displayed in bg_color\/fg_color, rinse, repeat;\n# if fg_color or bg_color, or both, is negative, no respective colorization takes place;\n# grid_type can be empty or contain one of the available values such as ascii, half-light, light, light-double-dash, etc...; see function init_grid_symbols();\nfunction show_table(title, result, maxw, display_width, requested_max_widths_str, wrap_str, truncate_str, ellipsis, colors, col_periods, grid_type)\n<\/pre>\n<p>This function also outputs the result set from an in-memory array into a table on the screen with optional colorization and gridding, e.g.:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-light-quadruple-dash-grid_RED-YELLOW_2-3-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-light-quadruple-dash-grid_RED-YELLOW_2-3-1.png\" alt=\"\" width=\"300\" height=\"90\" class=\"alignnone size-medium wp-image-54616\" \/><\/a><br \/>\nHowever, it goes into great lengths in attempting to shrink the table as much as possible to fit the screen size or the requested column widths. As showed by the above comments, it is also quite flexible with a long list of parameters. Fortunately, the parameters&#8217; complexity can be somewhat alleviated by calling it with simple, sensible parameters&#8217; values, or none at all, for a quick display and from there the presentation can be iteratively polished until the final result is found satisfactory.<br \/>\n<em>show_table()<\/em> takes the data to display from the associative array <em>result<\/em>, which has the same structure as used by function <em>simple_show_table()<\/em> above. When <em>maxw<\/em> is 0 (<em>maxw<\/em> stands for maximum widths), it checks whether a <em>display_width<\/em> is given; if so, it uses it, otherwise it uses the $COLUMNS environment variable to determine the screen width (note that $COLUMNS is not exported and therefore not visible in <em>gawk<\/em>&#8216;s ENVIRON associative array; therefore, it must be explicitly exported with the bash command <em>export $COLUMNS=$COLUMNS<\/em>). It shares this screen width between all the attributes to display, narrowing the ones that don&#8217;t fit or that don&#8217;t need that much space, but never narrower than <em>default_min_col<\/em> (currently set to 5 characters). Still, the resulting line length can exceed the screen width but further optimizations are available, keep reading. So the simplest invocation of the function is:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1; highlight: []\">\nshow_table(title, result)\n<\/pre>\n<p><a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-no-grid_no-color.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-no-grid_no-color.png\" alt=\"\" width=\"300\" height=\"60\" class=\"alignnone size-medium wp-image-54586\" \/><\/a><br \/>\nIt is also possible to force a common width to be used for each of the attributes by setting <em>maxw<\/em> to a positive value, e.g.:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-double-grid_green-black_2-5_maxw20.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-double-grid_green-black_2-5_maxw20.png\" alt=\"\" width=\"300\" height=\"85\" class=\"alignnone size-medium wp-image-54583\" \/><\/a><br \/>\nWhen <em>raw<\/em> is set -1 and no column sizing is specified in the parameter <em>requested_max_widths_str<\/em>, like in <em>simple_show_table()<\/em>, rows can be also printed in very long lines without explicit wrapping nor truncation but <em>show_table()<\/em> is smarter because it automatically wraps around repeating attributes yielding a tighter output in some cases, e.g.:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-light-quadruple-dash-grid_show-light-quadruple-dash-grid_GREEN-black_2-3_many-repeating.png_2-3_mawx-1_many-repeating.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-light-quadruple-dash-grid_show-light-quadruple-dash-grid_GREEN-black_2-3_many-repeating.png_2-3_mawx-1_many-repeating.png\" alt=\"\" width=\"300\" height=\"107\" class=\"alignnone size-medium wp-image-54582\" \/><\/a><br \/>\nHere is a better output showing the call trace and their parameters:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-light-quadruple-dash-grid_RED-YELLOW_2-3-2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/show-light-quadruple-dash-grid_RED-YELLOW_2-3-2.png\" alt=\"\" width=\"300\" height=\"90\" class=\"alignnone size-medium wp-image-54618\" \/><\/a><br \/>\nIf <em>raw<\/em> is set -1 and <em>requested_max_widths_str<\/em> are passed, the function uses them in the respective columns (the values in <em>requested_max_widths_str<\/em> are positional) and by default wraps around the attributes&#8217; text if too large. Positional strings of values in parameters <em>wrap_str<\/em> and <em>truncate_str<\/em> allow to control how text that exceeds the cell width is treated, either wrapped around or truncated. <em>wrap_str<\/em> mimicks what Oracle&#8217;s <em>sqlplus<\/em> does when using the command <em>col &#8230; format Ann<\/em>, e.g.:<br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/ascii-grid_max-1_custom_column_sizing_parameters-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/ascii-grid_max-1_custom_column_sizing_parameters-1.png\" alt=\"\" width=\"300\" height=\"28\" class=\"alignnone size-medium wp-image-54693\" \/><\/a><br \/>\n<a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/ascii-grid_max-1_custom_column_sizing.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/ascii-grid_max-1_custom_column_sizing.png\" alt=\"\" width=\"300\" height=\"207\" class=\"alignnone size-medium wp-image-54690\" \/><\/a><br \/>\nIf the terminal wraps the output into an unreadable mess, just pipe it into <em>less -S -R<\/em> and consider wrapping or truncating the text. Once in <em>less<\/em>, use the arrays keys to scroll laterally, optionally preceded by a number of characters to scroll by that amount, e.g. <em>1&#x27a1;<\/em>.<br \/>\nThe test program <em>tdctm.awk<\/em> already includes many examples of calls to both <em>*show_table()<\/em> functions; it can easily be used to test any parameter combination that best suit a particular result set.<\/p>\n<h3>Conclusion<\/h3>\n<p>The <em>gawk<\/em> interface to the Documentum API, <em>DctmAPI<\/em> for short, just went through some major surgery. It caught up with several enhancements that were presented in separate articles, sometimes implemented first in <em>DctmAPI.py<\/em> one year ago (see <a href=\"https:\/\/www.dbi-services.com\/blog\/dctmapi-py-revisited\/\">DctmAPI.py revisited<\/a>), its python counterpart. A lot of attention has been brought to the presentation of result sets, which may seem a bit out of scope, but this makes sense because data get extracted either to be exported somewhere else for further processing or to be visualized on screen or in some report; since it is more convenient to be able to do so from the same place, the interface does both.<br \/>\nThere is always room for improvement and this interface is no exception. Its usage will tell what it still lacks and how it will evolve. Any suggestions are welcome.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is part II of the article DctmAPI.awk revisited. See Part I here. The table presentation can be visually quite rich: it supports row colorization with optional color alternation and gridding, i.e. enclosing the table and data into a grid. Row colorization allows to colorize the data with a foreground color and an optional background [&hellip;]<\/p>\n","protected":false},"author":40,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[525],"tags":[],"type_dbi":[],"class_list":["post-17136","post","type-post","status-publish","format-standard","hentry","category-enterprise-content-management"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.5) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>DctmAPI.awk revisited (part II) - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"DctmAPI.awk revisited (part II)\" \/>\n<meta property=\"og:description\" content=\"This is part II of the article DctmAPI.awk revisited. See Part I here. The table presentation can be visually quite rich: it supports row colorization with optional color alternation and gridding, i.e. enclosing the table and data into a grid. Row colorization allows to colorize the data with a foreground color and an optional background [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-02-25T13:14:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-10-24T07:38:37+00:00\" \/>\n<meta name=\"author\" content=\"Middleware Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Middleware Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/\"},\"author\":{\"name\":\"Middleware Team\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d8563acfc6e604cce6507f45bac0ea1\"},\"headline\":\"DctmAPI.awk revisited (part II)\",\"datePublished\":\"2022-02-25T13:14:00+00:00\",\"dateModified\":\"2025-10-24T07:38:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/\"},\"wordCount\":1645,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2022\\\/02\\\/simple-grid_no-grid_yellow-noback-2.png\",\"articleSection\":[\"Enterprise content management\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/\",\"name\":\"DctmAPI.awk revisited (part II) - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2022\\\/02\\\/simple-grid_no-grid_yellow-noback-2.png\",\"datePublished\":\"2022-02-25T13:14:00+00:00\",\"dateModified\":\"2025-10-24T07:38:37+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d8563acfc6e604cce6507f45bac0ea1\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2022\\\/02\\\/simple-grid_no-grid_yellow-noback-2.png\",\"contentUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2022\\\/02\\\/simple-grid_no-grid_yellow-noback-2.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/dctmapi-awk-revisited-part-ii\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"DctmAPI.awk revisited (part II)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d8563acfc6e604cce6507f45bac0ea1\",\"name\":\"Middleware Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"caption\":\"Middleware Team\"},\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/author\\\/middleware-team\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"DctmAPI.awk revisited (part II) - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/","og_locale":"en_US","og_type":"article","og_title":"DctmAPI.awk revisited (part II)","og_description":"This is part II of the article DctmAPI.awk revisited. See Part I here. The table presentation can be visually quite rich: it supports row colorization with optional color alternation and gridding, i.e. enclosing the table and data into a grid. Row colorization allows to colorize the data with a foreground color and an optional background [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/","og_site_name":"dbi Blog","article_published_time":"2022-02-25T13:14:00+00:00","article_modified_time":"2025-10-24T07:38:37+00:00","author":"Middleware Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Middleware Team","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/"},"author":{"name":"Middleware Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1"},"headline":"DctmAPI.awk revisited (part II)","datePublished":"2022-02-25T13:14:00+00:00","dateModified":"2025-10-24T07:38:37+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/"},"wordCount":1645,"commentCount":0,"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-noback-2.png","articleSection":["Enterprise content management"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/","url":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/","name":"DctmAPI.awk revisited (part II) - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#primaryimage"},"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-noback-2.png","datePublished":"2022-02-25T13:14:00+00:00","dateModified":"2025-10-24T07:38:37+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#primaryimage","url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-noback-2.png","contentUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/02\/simple-grid_no-grid_yellow-noback-2.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/dctmapi-awk-revisited-part-ii\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"DctmAPI.awk revisited (part II)"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1","name":"Middleware Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","caption":"Middleware Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/middleware-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/17136","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/40"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=17136"}],"version-history":[{"count":1,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/17136\/revisions"}],"predecessor-version":[{"id":17137,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/17136\/revisions\/17137"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=17136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=17136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=17136"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=17136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}