Skip to content

Instantly share code, notes, and snippets.

@caruccio
Last active March 18, 2024 16:22
Show Gist options
  • Select an option

  • Save caruccio/804d53d19c7c993aba31dbd3da4c9d68 to your computer and use it in GitHub Desktop.

Select an option

Save caruccio/804d53d19c7c993aba31dbd3da4c9d68 to your computer and use it in GitHub Desktop.

Revisions

  1. caruccio revised this gist Mar 18, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion latest-version.md
    Original file line number Diff line number Diff line change
    @@ -78,7 +78,7 @@ At the next line for the same `$1.$2` index, the value will be `1`, thus negatin

    Note this only works if the input lines are sorted with the newest patch first, since awk will basically filter for the first item it finds.

    If you need to have the list sorted from newest to oldest, just use `sort -V` again:
    If you need to have the list sorted from oldest to newest, just use `sort -V` again:

    ```sh
    $ sort -Vr versions.txt | awk -F . '!a[$1 FS $2]++' | sort -V
  2. caruccio revised this gist Mar 18, 2024. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions latest-version.md
    Original file line number Diff line number Diff line change
    @@ -68,11 +68,13 @@ v1.22.10
    Let's analyse what `awk` does:

    - `-F .`: Uses `.` as the field separator. Each line will be splited by `.`, creating 3 fields: `$1=v1` (3 times), `$2=24|23|22` and `$3=4|2|10`.
    - `a[$1 FS $2]`: creates an associative array at position `$1 FS $2` (the values are concatenated), where `$1=v1` and `$2=24` (at the first input line), and `FS` if the field-separator (`.`). Since this posistion doen't exists, awk initializes it with `0`.
    - `a[$1 FS $2]++`: Increment the value `0` to `1`, turning it into a `true` value.
    - `!a[$1 FS $2]++`: Negate the value `true`, thus accepting the expression and printing the line. The block `{print}` is the default action for expressions with no code block.
    - `a[$1 FS $2]`: Creates an associative array `a `at position `$1 FS $2` (the values are concatenated), where `$1=v1` and `$2=24` (ex, at the first input line), and `FS` if the field-separator (`.`). Since this posistion doesn't exists, awk initializes it with `null`.
    - `a[$1 FS $2]++`: Postfix-increments the value from `0` (`null`) to `1`, turning it into a `true` value. The value `0` is used for the next instruction `!` and `1` is stored at `a[$1 FS $2]`.
    - `!a[$1 FS $2]++`: Negates the value `0` (`false`) to `1` (`true`), accepting the expression and printing the line.

    At the next line for the same `$1.$2`, the value will be already `1`, thus negating it (`!`) will change it to `0`, which evaluates to `false`, avoinding the default `{print}` code block.
    This is just an expression to accept code blocks to execute. When the code block is not defined, like this one, the default `{print}` is executed.

    At the next line for the same `$1.$2` index, the value will be `1`, thus negating it (`!`) will change it to `0`, which evaluates to `false`, avoinding the default `{print}` code block. Any other match for `$1.$2` will produce a `false` evaluation.

    Note this only works if the input lines are sorted with the newest patch first, since awk will basically filter for the first item it finds.

  3. caruccio revised this gist Mar 18, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion latest-version.md
    Original file line number Diff line number Diff line change
    @@ -68,7 +68,7 @@ v1.22.10
    Let's analyse what `awk` does:

    - `-F .`: Uses `.` as the field separator. Each line will be splited by `.`, creating 3 fields: `$1=v1` (3 times), `$2=24|23|22` and `$3=4|2|10`.
    - `a[$1 FS $2]`: creates an associative array at position `$1 FS $2`, where `$1=v1` and `$2=24` (at the first input line), and `FS` if the field-separator (`.`). Since this posistion doen't exists, aws initializes it with `0`.
    - `a[$1 FS $2]`: creates an associative array at position `$1 FS $2` (the values are concatenated), where `$1=v1` and `$2=24` (at the first input line), and `FS` if the field-separator (`.`). Since this posistion doen't exists, awk initializes it with `0`.
    - `a[$1 FS $2]++`: Increment the value `0` to `1`, turning it into a `true` value.
    - `!a[$1 FS $2]++`: Negate the value `true`, thus accepting the expression and printing the line. The block `{print}` is the default action for expressions with no code block.

  4. caruccio revised this gist Mar 18, 2024. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions latest-version.md
    Original file line number Diff line number Diff line change
    @@ -41,7 +41,7 @@ v1.24.4
    EOF
    ```

    Use sort's flags `-V` to sort by version number and `-r` to reverse the sorted values, from greatest to lowest:
    Use sort's flags `-V` to sort by version number and `-r` to reverse the sorted values, from newest to oldest:

    ```sh
    sort -Vr versions.txt
    @@ -56,7 +56,7 @@ v1.22.9
    v1.22.8
    ```

    Send this output to `awk` gives the latest version of each series:
    Sending this output to `awk` gives the latest version of each series:

    ```sh
    $ sort -Vr versions.txt | awk -F . '!a[$1 FS $2]++'
  5. caruccio revised this gist Mar 18, 2024. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions latest-version.md
    Original file line number Diff line number Diff line change
    @@ -74,4 +74,15 @@ Let's analyse what `awk` does:

    At the next line for the same `$1.$2`, the value will be already `1`, thus negating it (`!`) will change it to `0`, which evaluates to `false`, avoinding the default `{print}` code block.

    Note this only works if the input lines are sorted with the newest patch first, since awk will basically filter for the first item it finds.

    If you need to have the list sorted from newest to oldest, just use `sort -V` again:

    ```sh
    $ sort -Vr versions.txt | awk -F . '!a[$1 FS $2]++' | sort -V
    v1.22.10
    v1.23.2
    v1.24.4
    ```

    Genius!
  6. caruccio revised this gist Mar 18, 2024. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions latest-version.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    How to get the latest patch-level version from a list of distinct versions using bash and awk.
    This idea was taken from https://stackoverflow.com/a/21103864/1006369

    Supose you have this list of versions:
    Supose you have the following list of versions:

    ```
    v1.22.8
    @@ -15,7 +15,7 @@ v1.24.3
    v1.24.4 <-- latest v1.24 series
    ```

    And you need to extract the latest PATCH of each version serie. The result thus must be this:
    And you need to extract the latest PATCH of each version series. The result thus must be this:

    ```
    v1.22.10
  7. caruccio revised this gist Mar 18, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion latest-version.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    How to get the latest patch-level version from a list of distinct versions using bash and awk.
    This was taken from https://stackoverflow.com/a/21103864/1006369
    This idea was taken from https://stackoverflow.com/a/21103864/1006369

    Supose you have this list of versions:

  8. caruccio revised this gist Mar 18, 2024. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion latest-version.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    How to get the latest patch-level version from a list of distinct versions using bash and awk.
    This was taken from https://stackoverflow.com/a/21103864/1006369

    Supose you have this list of versions:

    @@ -69,4 +70,8 @@ Let's analyse what `awk` does:
    - `-F .`: Uses `.` as the field separator. Each line will be splited by `.`, creating 3 fields: `$1=v1` (3 times), `$2=24|23|22` and `$3=4|2|10`.
    - `a[$1 FS $2]`: creates an associative array at position `$1 FS $2`, where `$1=v1` and `$2=24` (at the first input line), and `FS` if the field-separator (`.`). Since this posistion doen't exists, aws initializes it with `0`.
    - `a[$1 FS $2]++`: Increment the value `0` to `1`, turning it into a `true` value.
    - `!a[$1 FS $2]++`: Negate the value `true`, thus accepting the expression and printing the line. The block `{ print }` is the default action for expressions with no code block.
    - `!a[$1 FS $2]++`: Negate the value `true`, thus accepting the expression and printing the line. The block `{print}` is the default action for expressions with no code block.

    At the next line for the same `$1.$2`, the value will be already `1`, thus negating it (`!`) will change it to `0`, which evaluates to `false`, avoinding the default `{print}` code block.

    Genius!
  9. caruccio renamed this gist Mar 18, 2024. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  10. caruccio created this gist Mar 18, 2024.
    72 changes: 72 additions & 0 deletions latest-version.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,72 @@
    How to get the latest patch-level version from a list of distinct versions using bash and awk.

    Supose you have this list of versions:

    ```
    v1.22.8
    v1.22.9
    v1.22.10 <-- latest v1.22 series
    v1.23.1
    v1.23.2 <-- latest v1.23 series
    v1.24.1
    v1.24.2
    v1.24.3
    v1.24.4 <-- latest v1.24 series
    ```

    And you need to extract the latest PATCH of each version serie. The result thus must be this:

    ```
    v1.22.10
    v1.23.2
    v1.24.4
    ```

    Using [AWK's pattern expressions](https://www.gnu.org/software/gawk/manual/gawk.html#Pattern-Elements) it's possible to evaluate only the first element of a associative-array, negate the eval and print (by default):

    First, create the file with the versions. It doesn't matter if it's sorted or not yet.

    ```sh
    $ cat >versions.txt <<EOF
    v1.22.8
    v1.22.9
    v1.22.10
    v1.23.1
    v1.23.2
    v1.24.1
    v1.24.2
    v1.24.3
    v1.24.4
    EOF
    ```

    Use sort's flags `-V` to sort by version number and `-r` to reverse the sorted values, from greatest to lowest:

    ```sh
    sort -Vr versions.txt
    v1.24.4
    v1.24.3
    v1.24.2
    v1.24.1
    v1.23.2
    v1.23.1
    v1.22.10
    v1.22.9
    v1.22.8
    ```

    Send this output to `awk` gives the latest version of each series:

    ```sh
    $ sort -Vr versions.txt | awk -F . '!a[$1 FS $2]++'
    v1.24.4
    v1.23.2
    v1.22.10
    ```

    Let's analyse what `awk` does:

    - `-F .`: Uses `.` as the field separator. Each line will be splited by `.`, creating 3 fields: `$1=v1` (3 times), `$2=24|23|22` and `$3=4|2|10`.
    - `a[$1 FS $2]`: creates an associative array at position `$1 FS $2`, where `$1=v1` and `$2=24` (at the first input line), and `FS` if the field-separator (`.`). Since this posistion doen't exists, aws initializes it with `0`.
    - `a[$1 FS $2]++`: Increment the value `0` to `1`, turning it into a `true` value.
    - `!a[$1 FS $2]++`: Negate the value `true`, thus accepting the expression and printing the line. The block `{ print }` is the default action for expressions with no code block.