• Re: Add 1 to each number in a column and keep the original format/blank

    From hongyi.zhao@gmail.com@21:1/5 to hongy...@gmail.com on Wed Sep 22 17:09:21 2021
    On Thursday, September 23, 2021 at 8:06:29 AM UTC+8, hongy...@gmail.com wrote:
    I have some stuff in a file like the following:

    you're right 1
    foo 2
    bar 3
    [...]


    I want to add 1 to each number in the last column and keep the original format/blank in the middle part of the line.

    Note: there maybe any number of blanks in the middle of the sentence.

    Any hints to achieve this goal?

    Regards,
    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From hongyi.zhao@gmail.com@21:1/5 to Janis Papanagnou on Wed Sep 22 18:13:14 2021
    On Thursday, September 23, 2021 at 8:58:59 AM UTC+8, Janis Papanagnou wrote:
    On 23.09.21 02:06, hongy...@gmail.com wrote:
    I have some stuff in a file like the following:

    you're right 1
    foo 2
    bar 3
    [...]


    I want to add 1 to each number in the last column and keep the original format/blank in the middle part of the line.
    vim yourfile
    /[0-9]\+$
    ^A
    n
    ^A
    ...
    n
    ^A

    (where ^A means to type <Ctrl>-A).

    This seems to require a lot of keystrokes. Therefore, for a large file, it may not be appropriate.


    Any hints to achieve this goal?
    Or use a script?

    In Awk substitute /[0-9]+$/ by $NF+1.

    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    In Emacs, perform the following on the selected region, as noted here [1]:

    C-u M-x shell-command-on-region RET awk '{sub(/[0-9]+$/, $NF+1); print}' RET

    [1] https://stackoverflow.com/a/2686806

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to hongy...@gmail.com on Thu Sep 23 02:58:56 2021
    On 23.09.21 02:06, hongy...@gmail.com wrote:
    I have some stuff in a file like the following:

    you're right 1
    foo 2
    bar 3
    [...]


    I want to add 1 to each number in the last column and keep the original format/blank in the middle part of the line.

    vim yourfile
    /[0-9]\+$
    ^A
    n
    ^A
    ...
    n
    ^A

    (where ^A means to type <Ctrl>-A).


    Any hints to achieve this goal?

    Or use a script?

    In Awk substitute /[0-9]+$/ by $NF+1.

    Janis


    Regards,
    HZ


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to hongy...@gmail.com on Thu Sep 23 03:24:34 2021
    On 23.09.21 03:13, hongy...@gmail.com wrote:
    On Thursday, September 23, 2021 at 8:58:59 AM UTC+8, Janis Papanagnou wrote:
    On 23.09.21 02:06, hongy...@gmail.com wrote:
    I have some stuff in a file like the following:

    you're right 1
    foo 2
    bar 3
    [...]


    I want to add 1 to each number in the last column and keep the original format/blank in the middle part of the line.
    vim yourfile
    /[0-9]\+$
    ^A
    n
    ^A
    ...
    n
    ^A

    (where ^A means to type <Ctrl>-A).

    This seems to require a lot of keystrokes. Therefore, for a large file, it may not be appropriate.

    Of course, but still valid given your under-specified requirements.
    For small files an in-place editor solution may be more appropriate.
    But to be honest, I didn't expect that you'd have asked for an editor
    solution.



    Any hints to achieve this goal?
    Or use a script?

    In Awk substitute /[0-9]+$/ by $NF+1.

    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    Which can be simplified if you have substitutions on every line to

    $ awk 'sub(/[0-9]+$/,$NF+1)' file


    Janis


    In Emacs, perform the following on the selected region, as noted here [1]:

    C-u M-x shell-command-on-region RET awk '{sub(/[0-9]+$/, $NF+1); print}' RET

    [1] https://stackoverflow.com/a/2686806


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From hongyi.zhao@gmail.com@21:1/5 to Tavis Ormandy on Wed Sep 22 19:55:08 2021
    On Thursday, September 23, 2021 at 10:40:01 AM UTC+8, Tavis Ormandy wrote:
    On 2021-09-23, Janis Papanagnou wrote:

    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    Which can be simplified if you have substitutions on every line to

    $ awk 'sub(/[0-9]+$/,$NF+1)' file

    Maybe even just awk '$NF++' :)

    This version doesn't keep the original blanks as they are:

    (datasci) werner@X10DAi-00:~$ cat 1111
    you're right 1
    fdf 2

    (datasci) werner@X10DAi-00:~$ awk 'sub(/[0-9]+$/,$NF+1)' 1111
    you're right 2
    fdf 3
    (datasci) werner@X10DAi-00:~$ awk '$NF++' 1111
    you're right 2
    fdf 3

    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tavis Ormandy@21:1/5 to Janis Papanagnou on Thu Sep 23 02:39:57 2021
    On 2021-09-23, Janis Papanagnou wrote:

    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    Which can be simplified if you have substitutions on every line to

    $ awk 'sub(/[0-9]+$/,$NF+1)' file


    Maybe even just awk '$NF++' :)

    Tavis.

    --
    _o) $ lynx lock.cmpxchg8b.com
    /\\ _o) _o) $ finger taviso@sdf.org
    _\_V _( ) _( ) @taviso

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tavis Ormandy@21:1/5 to hongy...@gmail.com on Thu Sep 23 03:37:01 2021
    On 2021-09-23, hongy...@gmail.com wrote:
    On Thursday, September 23, 2021 at 10:40:01 AM UTC+8, Tavis Ormandy wrote:
    On 2021-09-23, Janis Papanagnou wrote:

    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    Which can be simplified if you have substitutions on every line to

    $ awk 'sub(/[0-9]+$/,$NF+1)' file

    Maybe even just awk '$NF++' :)

    This version doesn't keep the original blanks as they are:


    Ahh, true, they'll be OFS separated. Too bad, it was so nice and clean :)

    Tavis.

    --
    _o) $ lynx lock.cmpxchg8b.com
    /\\ _o) _o) $ finger taviso@sdf.org
    _\_V _( ) _( ) @taviso

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eli the Bearded@21:1/5 to hongy...@gmail.com on Thu Sep 23 05:14:36 2021
    In comp.unix.shell, hongy...@gmail.com <hongyi.zhao@gmail.com> wrote:
    On Thursday, September 23, 2021 at 8:58:59 AM UTC+8, Janis Papanagnou wrote:
    (where ^A means to type <Ctrl>-A).
    This seems to require a lot of keystrokes. Therefore, for a large file, it may
    not be appropriate.

    I could, nay, have solved that with tail recursive macros in vim. It's
    kinda slow, and I only did it that way because it was a file needing
    hand editing besides number tweaking.

    In Awk substitute /[0-9]+$/ by $NF+1.
    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    This script was just asked about in c.l.p.m, so I happen to know it
    fails.

    $ cat file
    0
    a1
    aa 2
    aaa 3 4
    bbb
    ccc -2
    -1
    abc -2
    cba --3
    cab ---4
    bac ----5
    acb -----6
    $

    All of the lines with letters then negative numbers do not meet the
    requirement of add one to them.

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' /tmp/file
    1
    a1
    aa 3
    aaa 3 5
    bbb
    ccc --1
    -0
    abc --1
    cba --1
    cab ---1
    bac ----1
    acb -----1
    $ awk --version
    awk version 20121220
    $

    I got the same results with gawk (GNU Awk 5.0.1).

    In Emacs, perform the following on the selected region, as noted here [1]:

    C-u M-x shell-command-on-region RET awk '{sub(/[0-9]+$/, $NF+1); print}' RET

    In vim, I'd set a mark at start and end and (say 'ma' and 'mb') then

    :'a,'b ! awk ... RET

    There's certainly more than one way to do that, though. But first I'd
    want the awk command that works.

    My perl solution, which does add one to every natural number, and
    preserves white space, was this:

    perl -wpe 's/\b[0-9]+$/$&+1/e' file

    Elijah
    ------
    adding one to all integers or all reals needs a different solution

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eli the Bearded@21:1/5 to All on Thu Sep 23 06:14:56 2021
    In comp.unix.shell, I wrote:
    My perl solution, which does add one to every natural number, and
    preserves white space, was this:

    perl -wpe 's/\b[0-9]+$/$&+1/e' file

    I should note that for most purposes that's wrong. It doesn't consider
    negative values when adding one, and it doesn't enforce a white spaces separation of numbers from all other characters.

    This is a tad better, but should ---5 be treated as a number? Probably
    not.

    perl -wpe 's/\b-?[0-9]+$/$&+1/e' file

    Elijah
    ------
    it's too late to come up with a good short accurate version

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to janis_papanagnou@hotmail.com on Thu Sep 23 06:26:12 2021
    In article <sigl0i$139t$1@gioia.aioe.org>,
    Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
    ...
    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    Which can be simplified if you have substitutions on every line to

    $ awk 'sub(/[0-9]+$/,$NF+1)' file

    I usually do this sort of thing as:

    $ awk 'sub(/[0-9]+$/,$NF+1)+1' file

    But note that, sometimes, the filtering action (of skipping lines that are unexpected) is actually desirable - in which case, you don't want the +1.

    --
    "If our country is going broke, let it be from feeding the poor and caring for the elderly. And not from pampering the rich and fighting wars for them."

    --Living Blue in a Red State--

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Eli the Bearded on Thu Sep 23 11:01:55 2021
    On 23.09.21 07:14, Eli the Bearded wrote:
    In comp.unix.shell, hongy...@gmail.com <hongyi.zhao@gmail.com> wrote:
    On Thursday, September 23, 2021 at 8:58:59 AM UTC+8, Janis Papanagnou wrote: >>> (where ^A means to type <Ctrl>-A).
    This seems to require a lot of keystrokes. Therefore, for a large file, it may
    not be appropriate.

    I could, nay, have solved that with tail recursive macros in vim. It's
    kinda slow, and I only did it that way because it was a file needing
    hand editing besides number tweaking.

    In Awk substitute /[0-9]+$/ by $NF+1.
    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file

    This script was just asked about in c.l.p.m, so I happen to know it
    fails.

    $ cat file
    0
    a1
    aa 2
    aaa 3 4
    bbb
    ccc -2
    -1
    abc -2
    cba --3
    cab ---4
    bac ----5
    acb -----6
    $

    All of the lines with letters then negative numbers do not meet the requirement of add one to them.

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' /tmp/file
    1
    a1
    aa 3
    aaa 3 5
    bbb
    ccc --1
    -0
    abc --1
    cba --1
    cab ---1
    bac ----1
    acb -----1
    $ awk --version
    awk version 20121220
    $

    I got the same results with gawk (GNU Awk 5.0.1).

    The OP's examples and description ("columns") indicate that
    there's separated numbers, so most of your testcases don't
    match the requirement, and for those that do it works. For
    the case that negative numbers (or numbers with sign) shall
    also be considered that can be easily supported by adding
    an optional sign in the regexp: /[+-]?[0-9]+$/

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to janis_papanagnou@hotmail.com on Thu Sep 23 10:44:57 2021
    In article <f46957c8-63cb-5f09-6b0e-0b431e5010ba@hotmail.com>,
    Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
    ...
    also be considered that can be easily supported by adding
    an optional sign in the regexp: /[+-]?[0-9]+$/

    But then he'll just suggest:

    This a plus sign +27

    (Where OP wants that to become:

    This a plus sign +28
    )

    You are right, of course, that allowing there to be zero spaces before the number makes the problem hopelessly muddled.

    --
    The randomly chosen signature file that would have appeared here is more than 4 lines long. As such, it violates one or more Usenet RFCs. In order to remain in compliance with said RFCs, the actual sig can be found at the following URL:
    http://user.xmission.com/~gazelle/Sigs/FreeCollege

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From hongyi.zhao@gmail.com@21:1/5 to Eli the Bearded on Thu Sep 23 06:49:48 2021
    On Thursday, September 23, 2021 at 1:14:39 PM UTC+8, Eli the Bearded wrote:
    In comp.unix.shell, hongy...@gmail.com <hongy...@gmail.com> wrote:
    On Thursday, September 23, 2021 at 8:58:59 AM UTC+8, Janis Papanagnou wrote:
    (where ^A means to type <Ctrl>-A).
    This seems to require a lot of keystrokes. Therefore, for a large file, it may
    not be appropriate.
    I could, nay, have solved that with tail recursive macros in vim. It's
    kinda slow, and I only did it that way because it was a file needing
    hand editing besides number tweaking.
    In Awk substitute /[0-9]+$/ by $NF+1.
    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file
    This script was just asked about in c.l.p.m, so I happen to know it
    fails.

    $ cat file
    0
    a1
    aa 2
    aaa 3 4
    bbb
    ccc -2
    -1
    abc -2
    cba --3
    cab ---4
    bac ----5
    acb -----6
    $

    All of the lines with letters then negative numbers do not meet the requirement of add one to them.

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' /tmp/file
    1
    a1
    aa 3
    aaa 3 5
    bbb
    ccc --1
    -0
    abc --1
    cba --1
    cab ---1
    bac ----1
    acb -----1
    $ awk --version
    awk version 20121220
    $

    I got the same results with gawk (GNU Awk 5.0.1).

    I got the same results. Why does this happen?

    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to hongy...@gmail.com on Thu Sep 23 16:24:47 2021
    On 23.09.21 15:49, hongy...@gmail.com wrote:
    On Thursday, September 23, 2021 at 1:14:39 PM UTC+8, Eli the Bearded wrote:
    In comp.unix.shell, hongy...@gmail.com <hongy...@gmail.com> wrote:
    On Thursday, September 23, 2021 at 8:58:59 AM UTC+8, Janis Papanagnou wrote:
    (where ^A means to type <Ctrl>-A).
    This seems to require a lot of keystrokes. Therefore, for a large file, it may
    not be appropriate.
    I could, nay, have solved that with tail recursive macros in vim. It's
    kinda slow, and I only did it that way because it was a file needing
    hand editing besides number tweaking.
    In Awk substitute /[0-9]+$/ by $NF+1.
    Thank you. This does the trick:

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' file
    This script was just asked about in c.l.p.m, so I happen to know it
    fails.

    $ cat file
    0
    a1
    aa 2
    aaa 3 4
    bbb
    ccc -2
    -1
    abc -2
    cba --3
    cab ---4
    bac ----5
    acb -----6
    $

    All of the lines with letters then negative numbers do not meet the
    requirement of add one to them.

    $ awk '{sub(/[0-9]+$/, $NF+1); print}' /tmp/file
    1
    a1
    aa 3
    aaa 3 5
    bbb
    ccc --1
    -0
    abc --1
    cba --1
    cab ---1
    bac ----1
    acb -----1
    $ awk --version
    awk version 20121220
    $

    I got the same results with gawk (GNU Awk 5.0.1).

    I got the same results. Why does this happen?

    Because $NF addresses the last field, and most samples here have not
    a number as last field; $NF does not see a number (a1 is not a number,
    --1 is also not a number) like the one seen in your original samples.

    If your data would contain elements like
    abc def xyz999
    (i.e. a different syntax than in your OP) and you'd want as result
    abc def xyz1000
    then the algorithm needs adjustment to cover that; for example match
    the number, get that sub-string and add 1, replace it. (As opposed
    to simply access the data using $NF.)

    But since your requirements are anyway under-specified, as already
    mentioned upthread, it makes no sense to make any assumptions about
    potentially irregular data and provide solutions in advance that are unnecessarily more complex.

    Janis


    HZ


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Thu Sep 23 16:41:46 2021
    On 23.09.21 16:24, Janis Papanagnou wrote:

    If your data would contain elements like
    abc def xyz999
    (i.e. a different syntax than in your OP) and you'd want as result
    abc def xyz1000
    then the algorithm needs adjustment to cover that; for example match
    the number, get that sub-string and add 1, replace it. (As opposed
    to simply access the data using $NF.)

    Here's one way to cover such a requirement (just for illustration, not
    sure you really need that with your data)...

    awk 'match($0,/[+-]?[0-9]+$/) {
    print substr($0,1,RSTART-1) 1+substr($0,RSTART)
    }'


    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Thu Sep 23 18:46:32 2021
    On 23.09.21 16:41, Janis Papanagnou wrote:
    On 23.09.21 16:24, Janis Papanagnou wrote:

    If your data would contain elements like
    abc def xyz999
    (i.e. a different syntax than in your OP) and you'd want as result
    abc def xyz1000
    then the algorithm needs adjustment to cover that; for example match
    the number, get that sub-string and add 1, replace it. (As opposed
    to simply access the data using $NF.)

    I was not perfectly accurate here. With Awk it's of course also
    possible to apply that simple $NF access for that case as well;
    just define the field separator appropriately, e.g.

    awk -F '[^0-9+-]+' 'sub(/[+-]?[0-9]+$/,$NF+1)'

    then you can use even the same awk code as previously.

    Janis


    Here's one way to cover such a requirement (just for illustration, not
    sure you really need that with your data)...

    awk 'match($0,/[+-]?[0-9]+$/) {
    print substr($0,1,RSTART-1) 1+substr($0,RSTART)
    }'


    Janis


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eli the Bearded@21:1/5 to janis_papanagnou@hotmail.com on Thu Sep 23 17:28:30 2021
    In comp.unix.shell, Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
    Because $NF addresses the last field, and most samples here have not
    a number as last field; $NF does not see a number (a1 is not a number,
    --1 is also not a number) like the one seen in your original samples.

    I don't like that answer. It does not feel complete. The awk script
    will take 'a1' in and spit 'a1' out. But it does NOT take '--2' in
    and spit '--2' out.

    But since your requirements are anyway under-specified, as already
    mentioned upthread, it makes no sense to make any assumptions about potentially irregular data and provide solutions in advance that are unnecessarily more complex.

    It was very specified when I started to look at the problem. However
    that specification had little to do with the original one.

    Subject: The perl version of this command: awk '{sub(/[0-9]+$/, $NF+1); print}'.
    Newsgroups: comp.lang.perl.misc
    Message-ID: <c903cb65-a01e-4a3b-8443-ae69d470083bn@googlegroups.com>

    I attempted the problem, and found that I do not understand what awk is
    doing with lines that end /\s-+[0-9]+/ so I couldn't really come up
    with a Perl version without hard coding a bunch of cases.

    Elijah
    ------
    has comp.unix.shell after comp.lang.perl.misc in reading order

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Thu Sep 23 21:25:44 2021
    Should have been...

    On 23.09.21 21:21, Janis Papanagnou wrote:
    [...] The string "a2",

    The string "a1",

    interpreted as a numeric value by awk, yields the
    value 0. Adding 1 results in 1. And replacing the the _numeric_
    rest of the line (which is "1") again yields 1; together with the
    preceding "a" that's "a1". [...]

    Sorry for the typo.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Eli the Bearded on Thu Sep 23 21:21:11 2021
    On 23.09.21 19:28, Eli the Bearded wrote:
    In comp.unix.shell, Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
    Because $NF addresses the last field, and most samples here have not
    a number as last field; $NF does not see a number (a1 is not a number,
    --1 is also not a number) like the one seen in your original samples.

    I don't like that answer. It does not feel complete. The awk script
    will take 'a1' in and spit 'a1' out. But it does NOT take '--2' in
    and spit '--2' out.

    Well, we could also just say "trash in, trash out". Or specify the
    task more accurately and in a complete way (presuming the OP has a
    clear image of the data and requirements).

    Everything that is unspecified (data *and* program!) may behave as
    it wants. So what we can try to do is explain why specific random
    ad hoc data will lead to that behavior, and I give it another try
    for you. The substitution works on a pattern that is not bound to
    any fields, it operates on the whole string. Why? Because of the
    explicit "keep spacing intact" requirement. The substituted value
    on the other hand is taken for simplicity from the last _field_.
    That is valid if, as had been assumed, the last field contains a
    number (and not sequences of letters or punctuation and digits).
    Now you decided to challenge the test samples by such patterns.
    That's okay. But because that is outside the presumed specification
    we have to examine the behavior of the samples individually. The
    string "a2", interpreted as a numeric value by awk, yields the
    value 0. Adding 1 results in 1. And replacing the the _numeric_
    rest of the line (which is "1") again yields 1; together with the
    preceding "a" that's "a1". It would probably have been clearer
    if you'd have chosen "a3" as sample value (which would also have
    resulted in "a1"). The second sample "--2" is similar. It's not
    a valid number, so its interpreted value is 0 and adding 1 is 1.
    The substitution operates just on the digit part and replaces the
    "2" by the calculated 1.

    I think these detailed explanation should now make it obvious how
    the results emerged, and I hope you thus "like" this answer more
    than the terse one quoted above. But I haven't recapitulated every
    single test sample of yours, so if there's still one that puzzles
    you please feel free to ask.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)