|
1 | 1 | # Working with Tables |
2 | 2 |
|
| 3 | +[[toc]] |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
3 | 7 | One of the common ways of seeing data in Nu is through a table. Nu comes with a number of commands for working with tables to make it convenient to find what you're looking for, and for narrowing down the data to just what you need. |
4 | 8 |
|
5 | 9 | To start off, let's get a table that we can use: |
@@ -390,3 +394,191 @@ You can also [`reject`](/commands/docs/reject.md) columns in a table by passing |
390 | 394 | │ 7 │ /mnt │ dir │ │ rwxr-xr-x │ root │ root │ 0 B │ |
391 | 395 | ... |
392 | 396 | ``` |
| 397 | + |
| 398 | +### The # Index Column |
| 399 | + |
| 400 | +You've noticed that every table, by default, starts with a column with the heading `#`. This column can operate in one of two modes: |
| 401 | + |
| 402 | +1. Internal # |
| 403 | + |
| 404 | + - The default mode |
| 405 | + - Nushell provides a 0-based, consecutive index |
| 406 | + - Always corresponds to the cell-path row-number, where `select 0` will return the first item in the list, and `select <n-1>` returns the nth item |
| 407 | + - Is a display of an internal representation only. In other words, it is not accessible by column name. For example, `get index` will not work, nor `get #` |
| 408 | + |
| 409 | +1. "Index"-Renamed # |
| 410 | + |
| 411 | + - When a column named "index" is created, either directly or as a side-effect of another command, then this `index` column takes the place of the `#` column in the table display. In the table output, the column header is still `#`, but the _name_ of the column is now `index`. |
| 412 | + |
| 413 | + Example: |
| 414 | + |
| 415 | + ```nu |
| 416 | + ls | each { insert index { 1000 }} | first 5 |
| 417 | + # => ╭──────┬─────────────────┬──────┬─────────┬──────────────╮ |
| 418 | + # => │ # │ name │ type │ size │ modified │ |
| 419 | + # => ├──────┼─────────────────┼──────┼─────────┼──────────────┤ |
| 420 | + # => │ 1000 │ CNAME │ file │ 15 B │ 9 months ago │ |
| 421 | + # => │ 1000 │ CONTRIBUTING.md │ file │ 4.3 KiB │ 9 hours ago │ |
| 422 | + # => │ 1000 │ LICENSE │ file │ 1.0 KiB │ 9 months ago │ |
| 423 | + # => │ 1000 │ README.md │ file │ 2.2 KiB │ 3 weeks ago │ |
| 424 | + # => │ 1000 │ assets │ dir │ 4.0 KiB │ 9 months ago │ |
| 425 | + # => ╰──────┴─────────────────┴──────┴─────────┴──────────────╯ |
| 426 | + ``` |
| 427 | +
|
| 428 | + - If an `index` key is added to each row in the table, then it can be accessed via `select` and `get`: |
| 429 | +
|
| 430 | + ```nu |
| 431 | + ls | each { insert index { 1000 }} | first 5 | select index name |
| 432 | + # => ╭──────┬─────────────────╮ |
| 433 | + # => │ # │ name │ |
| 434 | + # => ├──────┼─────────────────┤ |
| 435 | + # => │ 1000 │ CNAME │ |
| 436 | + # => │ 1000 │ CONTRIBUTING.md │ |
| 437 | + # => │ 1000 │ LICENSE │ |
| 438 | + # => │ 1000 │ README.md │ |
| 439 | + # => │ 1000 │ assets │ |
| 440 | + # => ╰──────┴─────────────────╯ |
| 441 | + ``` |
| 442 | +
|
| 443 | + - On the other hand, if some rows have an `index` key and others don't, the result is no longer a table; it is a `list<any>` due to the different record types: |
| 444 | +
|
| 445 | + ```nu |
| 446 | + ls | upsert 3.index { "--->" } | first 5 |
| 447 | + # => ╭──────┬─────────────────┬──────┬─────────┬──────────────╮ |
| 448 | + # => │ # │ name │ type │ size │ modified │ |
| 449 | + # => ├──────┼─────────────────┼──────┼─────────┼──────────────┤ |
| 450 | + # => │ 0 │ CNAME │ file │ 15 B │ 9 months ago │ |
| 451 | + # => │ 1 │ CONTRIBUTING.md │ file │ 4.3 KiB │ 9 hours ago │ |
| 452 | + # => │ 2 │ LICENSE │ file │ 1.0 KiB │ 9 months ago │ |
| 453 | + # => │ ---> │ README.md │ file │ 2.2 KiB │ 3 weeks ago │ |
| 454 | + # => │ 4 │ assets │ dir │ 4.0 KiB │ 9 months ago │ |
| 455 | + # => ╰──────┴─────────────────┴──────┴─────────┴──────────────╯ |
| 456 | +
|
| 457 | + ls | upsert 3.index { "--->" } | first 5 | describe |
| 458 | + # => list<any> (stream) |
| 459 | +
|
| 460 | + ls | upsert 3.index { "--->" } | select index name |
| 461 | + # Error: cannot find column 'index' |
| 462 | +
|
| 463 | + ls | upsert 3.index { "--->" } | select index? name | first 5 |
| 464 | + # => ╭──────┬─────────────────╮ |
| 465 | + # => │ # │ name │ |
| 466 | + # => ├──────┼─────────────────┤ |
| 467 | + # => │ │ CNAME │ |
| 468 | + # => │ │ CONTRIBUTING.md │ |
| 469 | + # => │ │ LICENSE │ |
| 470 | + # => │ ---> │ README.md │ |
| 471 | + # => │ │ assets │ |
| 472 | + # => ╰──────┴─────────────────╯ |
| 473 | + ``` |
| 474 | +
|
| 475 | + - As demonstrated in the example above, any rows (records) in the table without an `index` key will continue to display the internal representation. |
| 476 | +
|
| 477 | +#### Additional Index Examples |
| 478 | +
|
| 479 | +##### Convert # to Index |
| 480 | +
|
| 481 | +A useful pattern for converting an internal `#` into an index for all rows, while maintaining the original numbering, is: |
| 482 | +
|
| 483 | +```nu |
| 484 | +ls | enumerate | flatten |
| 485 | +``` |
| 486 | + |
| 487 | +While the results _look_ the same, the `index` is now decoupled from the internal cell-path. For example: |
| 488 | + |
| 489 | +```nu |
| 490 | +ls | enumerate | flatten | sort-by modified | first 5 |
| 491 | +# => ╭────┬──────────────┬──────┬─────────┬──────────────╮ |
| 492 | +# => │ # │ name │ type │ size │ modified │ |
| 493 | +# => ├────┼──────────────┼──────┼─────────┼──────────────┤ |
| 494 | +# => │ 0 │ CNAME │ file │ 15 B │ 9 months ago │ |
| 495 | +# => │ 2 │ LICENSE │ file │ 1.0 KiB │ 9 months ago │ |
| 496 | +# => │ 4 │ assets │ dir │ 4.0 KiB │ 9 months ago │ |
| 497 | +# => │ 17 │ lefthook.yml │ file │ 1.1 KiB │ 9 months ago │ |
| 498 | +# => │ 24 │ snippets │ dir │ 4.0 KiB │ 9 months ago │ |
| 499 | +# => ╰────┴──────────────┴──────┴─────────┴──────────────╯ |
| 500 | +
|
| 501 | +ls | enumerate | flatten | sort-by modified | select 4 |
| 502 | +# => ╭────┬──────────┬──────┬─────────┬──────────────╮ |
| 503 | +# => │ # │ name │ type │ size │ modified │ |
| 504 | +# => ├────┼──────────┼──────┼─────────┼──────────────┤ |
| 505 | +# => │ 24 │ snippets │ dir │ 4.0 KiB │ 9 months ago │ |
| 506 | +# => ╰────┴──────────┴──────┴─────────┴──────────────╯ |
| 507 | +``` |
| 508 | + |
| 509 | +The `sort-by modified` now _also_ sorts the `index` along with the rest of the columns. |
| 510 | + |
| 511 | +##### Adding a Row Header |
| 512 | + |
| 513 | +```nu |
| 514 | +let table = [ |
| 515 | +[additions deletions delta ]; |
| 516 | +[ 10 20 -10 ] |
| 517 | +[ 15 5 10 ] |
| 518 | +[ 8 6 2 ]] |
| 519 | +
|
| 520 | +let totals_row = ($table | math sum | insert index {"Totals"}) |
| 521 | +$table | append $totals_row |
| 522 | +# => ╭────────┬───────────┬───────────┬───────╮ |
| 523 | +# => │ # │ additions │ deletions │ delta │ |
| 524 | +# => ├────────┼───────────┼───────────┼───────┤ |
| 525 | +# => │ 0 │ 10 │ 20 │ -10 │ |
| 526 | +# => │ 1 │ 15 │ 5 │ 10 │ |
| 527 | +# => │ 2 │ 8 │ 6 │ 2 │ |
| 528 | +# => │ Totals │ 33 │ 31 │ 2 │ |
| 529 | +# => ╰────────┴───────────┴───────────┴───────╯ |
| 530 | +``` |
| 531 | + |
| 532 | +### The `table` command |
| 533 | + |
| 534 | +The [`table`](/commands/docs/table.md) command is used to _render_ structured data. This includes: |
| 535 | + |
| 536 | +- Tables |
| 537 | +- Lists |
| 538 | +- Records |
| 539 | +- Ranges |
| 540 | + |
| 541 | +Perhaps contrary to initial assumptions, the result of rendering these types is a `string`. For example: |
| 542 | + |
| 543 | +```nu |
| 544 | +[ Nagasaki Ghent Cambridge Izmir Graz Lubango ] | table | describe |
| 545 | +# => string (stream) |
| 546 | +``` |
| 547 | + |
| 548 | +Other data types are passed through the `table` command unchanged. |
| 549 | + |
| 550 | +With no arguments, the output rendered from the `table` command will often _display_ the same as unrendered form. For example: |
| 551 | + |
| 552 | +```nu |
| 553 | +[ Nagasaki Ghent Cambridge Izmir Graz Lubango ] |
| 554 | +# => ╭───┬───────────╮ |
| 555 | +# => │ 0 │ Nagasaki │ |
| 556 | +# => │ 1 │ Ghent │ |
| 557 | +# => │ 2 │ Cambridge │ |
| 558 | +# => │ 3 │ Izmir │ |
| 559 | +# => │ 4 │ Graz │ |
| 560 | +# => │ 5 │ Lubango │ |
| 561 | +# => ╰───┴───────────╯ |
| 562 | +[ Nagasaki Ghent Cambridge Izmir Graz Lubango ] | table |
| 563 | +# => ╭───┬───────────╮ |
| 564 | +# => │ 0 │ Nagasaki │ |
| 565 | +# => │ 1 │ Ghent │ |
| 566 | +# => │ 2 │ Cambridge │ |
| 567 | +# => │ 3 │ Izmir │ |
| 568 | +# => │ 4 │ Graz │ |
| 569 | +# => │ 5 │ Lubango │ |
| 570 | +# => ╰───┴───────────╯ |
| 571 | +``` |
| 572 | + |
| 573 | +This can be useful when you need to store the rendered view of structured data as a string. For example, to remove all ANSI formatting (colors) from a table: |
| 574 | + |
| 575 | +``` |
| 576 | +ls | table | ansi strip |
| 577 | +``` |
| 578 | + |
| 579 | +The `table` command also has multiple options for _changing_ the rendering of a table, such as: |
| 580 | + |
| 581 | +- `-e` to expand data that would normally be collapsed when rendering. Compare `scope modules | table` to `scope modules | table -e`. |
| 582 | +- `-i false` to hide the `index`/`#` column |
| 583 | +- `-a 5` to abbreviate the table to just the first and last 5 entries |
| 584 | +- And more |
0 commit comments