How to increment the last number in a string; bash
I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing
I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.
The above example would result in /foo/bar/baz59_ 6stuff.thing
I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?
awk/sed/bash/grep are all viable.
bash perl awk sed
|
show 2 more comments
I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing
I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.
The above example would result in /foo/bar/baz59_ 6stuff.thing
I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?
awk/sed/bash/grep are all viable.
bash perl awk sed
1
If the last number is 9, what's the desired outcome? What if it's 59?
– James Brown
Jan 25 at 14:38
1
if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)
– UKMonkey
Jan 25 at 14:42
It's always preceded by an underscore this last number of yours?
– gboffi
Jan 25 at 14:58
@gboffi no; the previous character is not fixed.
– UKMonkey
Jan 25 at 15:01
if it's greater than a script argument
you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?
– ysth
Jan 25 at 15:31
|
show 2 more comments
I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing
I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.
The above example would result in /foo/bar/baz59_ 6stuff.thing
I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?
awk/sed/bash/grep are all viable.
bash perl awk sed
I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing
I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.
The above example would result in /foo/bar/baz59_ 6stuff.thing
I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?
awk/sed/bash/grep are all viable.
bash perl awk sed
bash perl awk sed
edited Jan 25 at 16:12
UKMonkey
asked Jan 25 at 14:34
UKMonkeyUKMonkey
5,69431227
5,69431227
1
If the last number is 9, what's the desired outcome? What if it's 59?
– James Brown
Jan 25 at 14:38
1
if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)
– UKMonkey
Jan 25 at 14:42
It's always preceded by an underscore this last number of yours?
– gboffi
Jan 25 at 14:58
@gboffi no; the previous character is not fixed.
– UKMonkey
Jan 25 at 15:01
if it's greater than a script argument
you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?
– ysth
Jan 25 at 15:31
|
show 2 more comments
1
If the last number is 9, what's the desired outcome? What if it's 59?
– James Brown
Jan 25 at 14:38
1
if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)
– UKMonkey
Jan 25 at 14:42
It's always preceded by an underscore this last number of yours?
– gboffi
Jan 25 at 14:58
@gboffi no; the previous character is not fixed.
– UKMonkey
Jan 25 at 15:01
if it's greater than a script argument
you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?
– ysth
Jan 25 at 15:31
1
1
If the last number is 9, what's the desired outcome? What if it's 59?
– James Brown
Jan 25 at 14:38
If the last number is 9, what's the desired outcome? What if it's 59?
– James Brown
Jan 25 at 14:38
1
1
if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)
– UKMonkey
Jan 25 at 14:42
if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)
– UKMonkey
Jan 25 at 14:42
It's always preceded by an underscore this last number of yours?
– gboffi
Jan 25 at 14:58
It's always preceded by an underscore this last number of yours?
– gboffi
Jan 25 at 14:58
@gboffi no; the previous character is not fixed.
– UKMonkey
Jan 25 at 15:01
@gboffi no; the previous character is not fixed.
– UKMonkey
Jan 25 at 15:01
if it's greater than a script argument
you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?– ysth
Jan 25 at 15:31
if it's greater than a script argument
you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?– ysth
Jan 25 at 15:31
|
show 2 more comments
6 Answers
6
active
oldest
votes
Updated Answer
Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:
perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<< "abc123_456.txt" -- -thresh=500
Original Answer
You can evaluate/calculate a replacement with /e
in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:
perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt
The (?!.*d+)
is (hopefully) a negative look-ahead for any more digits.
The $1
represents any sequence of digits captured in the capture group (d+)
.
Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.
This seems to work perfectly; and even handles a string containing quotes
– UKMonkey
Jan 25 at 15:06
5
ors/.*(?<!d)K(d+)/$1+1/sea
– ysth
Jan 25 at 15:27
2
@EdMorton Well spotted! I hadn't seen that, but have added it in now.
– Mark Setchell
Jan 25 at 17:16
1
ors/(d+)(?=D*$)/$1+1/ea
– Miller
Jan 25 at 20:17
Thank you all for your alternative suggestions.
– Mark Setchell
Jan 25 at 20:55
add a comment |
Using bash regular expression matching:
$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]
OK, what do we have now?
$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")
So we can construct the new filename
if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
new=${prefix}${number}${BASH_REMATCH[2]}
echo $new
fi
# => /foo/bar/baz59_ 100stuff.thing
add a comment |
With GNU awk for the 3rd arg to match():
$ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 6stuff.thing
Just set t
to whatever your threshold value is for incrementing, e.g.:
$ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 5stuff.thing
add a comment |
if it's greater than a script argument.
If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.
cat script.ksh
value=$1
echo "/foo/bar/baz59_ 5stuff.thing" |
awk -v arg="$value" '
match($2,/[0-9]+/){
val=substr($2,RSTART,RLENGTH)
val=val<arg?val+1:val
$2=val substr($2,RSTART+RLENGTH)
}
1'
Here is an example when I run script.ksh it gives following output.
/script.ksh 7
/foo/bar/baz59_ 6stuff.thing
@UKMonkey, could you please check this one also once and let me know if this works for you?
– RavinderSingh13
Jan 25 at 15:09
1
works fine! thanks
– UKMonkey
Jan 25 at 15:12
@UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)
– RavinderSingh13
Jan 25 at 15:18
it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.
– UKMonkey
Jan 25 at 15:26
@UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)
– RavinderSingh13
Jan 25 at 15:29
add a comment |
Here is a shorter gnu awk
approach:
cat incr.awk
{
n = split($0, a, /[0-9]+/, b)
for(i=1; i<n; i++)
s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
print s a[i]
}
Then use it as:
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
/foo/bar/baz59_ 6stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
/foo/bar/baz59_ 90stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
/foo/bar/stuff.thing
add a comment |
An awk:
$ echo /foo/bar/baz59_ 99stuff.thing |
awk '
/[0-9]/ {
rstart=1 # keep track of the start
while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
rstart+=RSTART+RLENGTH-1 # increase rstart
rlength=RLENGTH # remember length too
}
v=substr($0,rstart-rlength,rlength)+1 # increase last number
print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
next
}1' # in case there was no number
/foo/bar/baz59_ 100stuff.thing
Edit:
Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):
$ echo /foo/bar/baz59_ 99stuff.thing |
awk -v arg=100 '
/[0-9]/ {
rstart=1
while(match(substr($0,rstart),/[0-9]+/)) {
rstart+=RSTART+RLENGTH-1
rlength=RLENGTH
}
v=substr($0,rstart-rlength,rlength)
if(0+v>arg) { # test if v greater that argument
print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
next
}
}1'
Output now:
/foo/bar/baz59_ 99stuff.thing
Updated with the script argument requirement. Missed it at first.
– James Brown
Jan 25 at 15:58
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54367360%2fhow-to-increment-the-last-number-in-a-string-bash%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
Updated Answer
Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:
perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<< "abc123_456.txt" -- -thresh=500
Original Answer
You can evaluate/calculate a replacement with /e
in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:
perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt
The (?!.*d+)
is (hopefully) a negative look-ahead for any more digits.
The $1
represents any sequence of digits captured in the capture group (d+)
.
Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.
This seems to work perfectly; and even handles a string containing quotes
– UKMonkey
Jan 25 at 15:06
5
ors/.*(?<!d)K(d+)/$1+1/sea
– ysth
Jan 25 at 15:27
2
@EdMorton Well spotted! I hadn't seen that, but have added it in now.
– Mark Setchell
Jan 25 at 17:16
1
ors/(d+)(?=D*$)/$1+1/ea
– Miller
Jan 25 at 20:17
Thank you all for your alternative suggestions.
– Mark Setchell
Jan 25 at 20:55
add a comment |
Updated Answer
Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:
perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<< "abc123_456.txt" -- -thresh=500
Original Answer
You can evaluate/calculate a replacement with /e
in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:
perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt
The (?!.*d+)
is (hopefully) a negative look-ahead for any more digits.
The $1
represents any sequence of digits captured in the capture group (d+)
.
Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.
This seems to work perfectly; and even handles a string containing quotes
– UKMonkey
Jan 25 at 15:06
5
ors/.*(?<!d)K(d+)/$1+1/sea
– ysth
Jan 25 at 15:27
2
@EdMorton Well spotted! I hadn't seen that, but have added it in now.
– Mark Setchell
Jan 25 at 17:16
1
ors/(d+)(?=D*$)/$1+1/ea
– Miller
Jan 25 at 20:17
Thank you all for your alternative suggestions.
– Mark Setchell
Jan 25 at 20:55
add a comment |
Updated Answer
Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:
perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<< "abc123_456.txt" -- -thresh=500
Original Answer
You can evaluate/calculate a replacement with /e
in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:
perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt
The (?!.*d+)
is (hopefully) a negative look-ahead for any more digits.
The $1
represents any sequence of digits captured in the capture group (d+)
.
Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.
Updated Answer
Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:
perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<< "abc123_456.txt" -- -thresh=500
Original Answer
You can evaluate/calculate a replacement with /e
in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:
perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt
The (?!.*d+)
is (hopefully) a negative look-ahead for any more digits.
The $1
represents any sequence of digits captured in the capture group (d+)
.
Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.
edited Jan 25 at 17:15
answered Jan 25 at 14:58
Mark SetchellMark Setchell
88.6k676176
88.6k676176
This seems to work perfectly; and even handles a string containing quotes
– UKMonkey
Jan 25 at 15:06
5
ors/.*(?<!d)K(d+)/$1+1/sea
– ysth
Jan 25 at 15:27
2
@EdMorton Well spotted! I hadn't seen that, but have added it in now.
– Mark Setchell
Jan 25 at 17:16
1
ors/(d+)(?=D*$)/$1+1/ea
– Miller
Jan 25 at 20:17
Thank you all for your alternative suggestions.
– Mark Setchell
Jan 25 at 20:55
add a comment |
This seems to work perfectly; and even handles a string containing quotes
– UKMonkey
Jan 25 at 15:06
5
ors/.*(?<!d)K(d+)/$1+1/sea
– ysth
Jan 25 at 15:27
2
@EdMorton Well spotted! I hadn't seen that, but have added it in now.
– Mark Setchell
Jan 25 at 17:16
1
ors/(d+)(?=D*$)/$1+1/ea
– Miller
Jan 25 at 20:17
Thank you all for your alternative suggestions.
– Mark Setchell
Jan 25 at 20:55
This seems to work perfectly; and even handles a string containing quotes
– UKMonkey
Jan 25 at 15:06
This seems to work perfectly; and even handles a string containing quotes
– UKMonkey
Jan 25 at 15:06
5
5
or
s/.*(?<!d)K(d+)/$1+1/sea
– ysth
Jan 25 at 15:27
or
s/.*(?<!d)K(d+)/$1+1/sea
– ysth
Jan 25 at 15:27
2
2
@EdMorton Well spotted! I hadn't seen that, but have added it in now.
– Mark Setchell
Jan 25 at 17:16
@EdMorton Well spotted! I hadn't seen that, but have added it in now.
– Mark Setchell
Jan 25 at 17:16
1
1
or
s/(d+)(?=D*$)/$1+1/ea
– Miller
Jan 25 at 20:17
or
s/(d+)(?=D*$)/$1+1/ea
– Miller
Jan 25 at 20:17
Thank you all for your alternative suggestions.
– Mark Setchell
Jan 25 at 20:55
Thank you all for your alternative suggestions.
– Mark Setchell
Jan 25 at 20:55
add a comment |
Using bash regular expression matching:
$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]
OK, what do we have now?
$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")
So we can construct the new filename
if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
new=${prefix}${number}${BASH_REMATCH[2]}
echo $new
fi
# => /foo/bar/baz59_ 100stuff.thing
add a comment |
Using bash regular expression matching:
$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]
OK, what do we have now?
$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")
So we can construct the new filename
if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
new=${prefix}${number}${BASH_REMATCH[2]}
echo $new
fi
# => /foo/bar/baz59_ 100stuff.thing
add a comment |
Using bash regular expression matching:
$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]
OK, what do we have now?
$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")
So we can construct the new filename
if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
new=${prefix}${number}${BASH_REMATCH[2]}
echo $new
fi
# => /foo/bar/baz59_ 100stuff.thing
Using bash regular expression matching:
$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]
OK, what do we have now?
$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")
So we can construct the new filename
if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
new=${prefix}${number}${BASH_REMATCH[2]}
echo $new
fi
# => /foo/bar/baz59_ 100stuff.thing
edited Jan 25 at 15:22
answered Jan 25 at 15:10
glenn jackmanglenn jackman
167k26145237
167k26145237
add a comment |
add a comment |
With GNU awk for the 3rd arg to match():
$ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 6stuff.thing
Just set t
to whatever your threshold value is for incrementing, e.g.:
$ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 5stuff.thing
add a comment |
With GNU awk for the 3rd arg to match():
$ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 6stuff.thing
Just set t
to whatever your threshold value is for incrementing, e.g.:
$ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 5stuff.thing
add a comment |
With GNU awk for the 3rd arg to match():
$ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 6stuff.thing
Just set t
to whatever your threshold value is for incrementing, e.g.:
$ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 5stuff.thing
With GNU awk for the 3rd arg to match():
$ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 6stuff.thing
Just set t
to whatever your threshold value is for incrementing, e.g.:
$ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
/foo/bar/baz59_ 5stuff.thing
answered Jan 25 at 16:58
Ed MortonEd Morton
109k124598
109k124598
add a comment |
add a comment |
if it's greater than a script argument.
If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.
cat script.ksh
value=$1
echo "/foo/bar/baz59_ 5stuff.thing" |
awk -v arg="$value" '
match($2,/[0-9]+/){
val=substr($2,RSTART,RLENGTH)
val=val<arg?val+1:val
$2=val substr($2,RSTART+RLENGTH)
}
1'
Here is an example when I run script.ksh it gives following output.
/script.ksh 7
/foo/bar/baz59_ 6stuff.thing
@UKMonkey, could you please check this one also once and let me know if this works for you?
– RavinderSingh13
Jan 25 at 15:09
1
works fine! thanks
– UKMonkey
Jan 25 at 15:12
@UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)
– RavinderSingh13
Jan 25 at 15:18
it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.
– UKMonkey
Jan 25 at 15:26
@UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)
– RavinderSingh13
Jan 25 at 15:29
add a comment |
if it's greater than a script argument.
If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.
cat script.ksh
value=$1
echo "/foo/bar/baz59_ 5stuff.thing" |
awk -v arg="$value" '
match($2,/[0-9]+/){
val=substr($2,RSTART,RLENGTH)
val=val<arg?val+1:val
$2=val substr($2,RSTART+RLENGTH)
}
1'
Here is an example when I run script.ksh it gives following output.
/script.ksh 7
/foo/bar/baz59_ 6stuff.thing
@UKMonkey, could you please check this one also once and let me know if this works for you?
– RavinderSingh13
Jan 25 at 15:09
1
works fine! thanks
– UKMonkey
Jan 25 at 15:12
@UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)
– RavinderSingh13
Jan 25 at 15:18
it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.
– UKMonkey
Jan 25 at 15:26
@UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)
– RavinderSingh13
Jan 25 at 15:29
add a comment |
if it's greater than a script argument.
If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.
cat script.ksh
value=$1
echo "/foo/bar/baz59_ 5stuff.thing" |
awk -v arg="$value" '
match($2,/[0-9]+/){
val=substr($2,RSTART,RLENGTH)
val=val<arg?val+1:val
$2=val substr($2,RSTART+RLENGTH)
}
1'
Here is an example when I run script.ksh it gives following output.
/script.ksh 7
/foo/bar/baz59_ 6stuff.thing
if it's greater than a script argument.
If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.
cat script.ksh
value=$1
echo "/foo/bar/baz59_ 5stuff.thing" |
awk -v arg="$value" '
match($2,/[0-9]+/){
val=substr($2,RSTART,RLENGTH)
val=val<arg?val+1:val
$2=val substr($2,RSTART+RLENGTH)
}
1'
Here is an example when I run script.ksh it gives following output.
/script.ksh 7
/foo/bar/baz59_ 6stuff.thing
edited Jan 25 at 15:10
answered Jan 25 at 14:56
RavinderSingh13RavinderSingh13
27.3k41538
27.3k41538
@UKMonkey, could you please check this one also once and let me know if this works for you?
– RavinderSingh13
Jan 25 at 15:09
1
works fine! thanks
– UKMonkey
Jan 25 at 15:12
@UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)
– RavinderSingh13
Jan 25 at 15:18
it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.
– UKMonkey
Jan 25 at 15:26
@UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)
– RavinderSingh13
Jan 25 at 15:29
add a comment |
@UKMonkey, could you please check this one also once and let me know if this works for you?
– RavinderSingh13
Jan 25 at 15:09
1
works fine! thanks
– UKMonkey
Jan 25 at 15:12
@UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)
– RavinderSingh13
Jan 25 at 15:18
it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.
– UKMonkey
Jan 25 at 15:26
@UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)
– RavinderSingh13
Jan 25 at 15:29
@UKMonkey, could you please check this one also once and let me know if this works for you?
– RavinderSingh13
Jan 25 at 15:09
@UKMonkey, could you please check this one also once and let me know if this works for you?
– RavinderSingh13
Jan 25 at 15:09
1
1
works fine! thanks
– UKMonkey
Jan 25 at 15:12
works fine! thanks
– UKMonkey
Jan 25 at 15:12
@UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)
– RavinderSingh13
Jan 25 at 15:18
@UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)
– RavinderSingh13
Jan 25 at 15:18
it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.
– UKMonkey
Jan 25 at 15:26
it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.
– UKMonkey
Jan 25 at 15:26
@UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)
– RavinderSingh13
Jan 25 at 15:29
@UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)
– RavinderSingh13
Jan 25 at 15:29
add a comment |
Here is a shorter gnu awk
approach:
cat incr.awk
{
n = split($0, a, /[0-9]+/, b)
for(i=1; i<n; i++)
s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
print s a[i]
}
Then use it as:
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
/foo/bar/baz59_ 6stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
/foo/bar/baz59_ 90stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
/foo/bar/stuff.thing
add a comment |
Here is a shorter gnu awk
approach:
cat incr.awk
{
n = split($0, a, /[0-9]+/, b)
for(i=1; i<n; i++)
s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
print s a[i]
}
Then use it as:
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
/foo/bar/baz59_ 6stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
/foo/bar/baz59_ 90stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
/foo/bar/stuff.thing
add a comment |
Here is a shorter gnu awk
approach:
cat incr.awk
{
n = split($0, a, /[0-9]+/, b)
for(i=1; i<n; i++)
s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
print s a[i]
}
Then use it as:
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
/foo/bar/baz59_ 6stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
/foo/bar/baz59_ 90stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
/foo/bar/stuff.thing
Here is a shorter gnu awk
approach:
cat incr.awk
{
n = split($0, a, /[0-9]+/, b)
for(i=1; i<n; i++)
s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
print s a[i]
}
Then use it as:
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
/foo/bar/baz59_ 6stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
/foo/bar/baz59_ 90stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
/foo/bar/baz59_ 80stuff.thing
awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
/foo/bar/stuff.thing
answered Jan 25 at 15:28
anubhavaanubhava
525k46323397
525k46323397
add a comment |
add a comment |
An awk:
$ echo /foo/bar/baz59_ 99stuff.thing |
awk '
/[0-9]/ {
rstart=1 # keep track of the start
while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
rstart+=RSTART+RLENGTH-1 # increase rstart
rlength=RLENGTH # remember length too
}
v=substr($0,rstart-rlength,rlength)+1 # increase last number
print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
next
}1' # in case there was no number
/foo/bar/baz59_ 100stuff.thing
Edit:
Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):
$ echo /foo/bar/baz59_ 99stuff.thing |
awk -v arg=100 '
/[0-9]/ {
rstart=1
while(match(substr($0,rstart),/[0-9]+/)) {
rstart+=RSTART+RLENGTH-1
rlength=RLENGTH
}
v=substr($0,rstart-rlength,rlength)
if(0+v>arg) { # test if v greater that argument
print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
next
}
}1'
Output now:
/foo/bar/baz59_ 99stuff.thing
Updated with the script argument requirement. Missed it at first.
– James Brown
Jan 25 at 15:58
add a comment |
An awk:
$ echo /foo/bar/baz59_ 99stuff.thing |
awk '
/[0-9]/ {
rstart=1 # keep track of the start
while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
rstart+=RSTART+RLENGTH-1 # increase rstart
rlength=RLENGTH # remember length too
}
v=substr($0,rstart-rlength,rlength)+1 # increase last number
print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
next
}1' # in case there was no number
/foo/bar/baz59_ 100stuff.thing
Edit:
Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):
$ echo /foo/bar/baz59_ 99stuff.thing |
awk -v arg=100 '
/[0-9]/ {
rstart=1
while(match(substr($0,rstart),/[0-9]+/)) {
rstart+=RSTART+RLENGTH-1
rlength=RLENGTH
}
v=substr($0,rstart-rlength,rlength)
if(0+v>arg) { # test if v greater that argument
print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
next
}
}1'
Output now:
/foo/bar/baz59_ 99stuff.thing
Updated with the script argument requirement. Missed it at first.
– James Brown
Jan 25 at 15:58
add a comment |
An awk:
$ echo /foo/bar/baz59_ 99stuff.thing |
awk '
/[0-9]/ {
rstart=1 # keep track of the start
while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
rstart+=RSTART+RLENGTH-1 # increase rstart
rlength=RLENGTH # remember length too
}
v=substr($0,rstart-rlength,rlength)+1 # increase last number
print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
next
}1' # in case there was no number
/foo/bar/baz59_ 100stuff.thing
Edit:
Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):
$ echo /foo/bar/baz59_ 99stuff.thing |
awk -v arg=100 '
/[0-9]/ {
rstart=1
while(match(substr($0,rstart),/[0-9]+/)) {
rstart+=RSTART+RLENGTH-1
rlength=RLENGTH
}
v=substr($0,rstart-rlength,rlength)
if(0+v>arg) { # test if v greater that argument
print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
next
}
}1'
Output now:
/foo/bar/baz59_ 99stuff.thing
An awk:
$ echo /foo/bar/baz59_ 99stuff.thing |
awk '
/[0-9]/ {
rstart=1 # keep track of the start
while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
rstart+=RSTART+RLENGTH-1 # increase rstart
rlength=RLENGTH # remember length too
}
v=substr($0,rstart-rlength,rlength)+1 # increase last number
print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
next
}1' # in case there was no number
/foo/bar/baz59_ 100stuff.thing
Edit:
Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):
$ echo /foo/bar/baz59_ 99stuff.thing |
awk -v arg=100 '
/[0-9]/ {
rstart=1
while(match(substr($0,rstart),/[0-9]+/)) {
rstart+=RSTART+RLENGTH-1
rlength=RLENGTH
}
v=substr($0,rstart-rlength,rlength)
if(0+v>arg) { # test if v greater that argument
print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
next
}
}1'
Output now:
/foo/bar/baz59_ 99stuff.thing
edited Jan 25 at 15:56
answered Jan 25 at 15:10
James BrownJames Brown
18.6k31635
18.6k31635
Updated with the script argument requirement. Missed it at first.
– James Brown
Jan 25 at 15:58
add a comment |
Updated with the script argument requirement. Missed it at first.
– James Brown
Jan 25 at 15:58
Updated with the script argument requirement. Missed it at first.
– James Brown
Jan 25 at 15:58
Updated with the script argument requirement. Missed it at first.
– James Brown
Jan 25 at 15:58
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54367360%2fhow-to-increment-the-last-number-in-a-string-bash%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
If the last number is 9, what's the desired outcome? What if it's 59?
– James Brown
Jan 25 at 14:38
1
if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)
– UKMonkey
Jan 25 at 14:42
It's always preceded by an underscore this last number of yours?
– gboffi
Jan 25 at 14:58
@gboffi no; the previous character is not fixed.
– UKMonkey
Jan 25 at 15:01
if it's greater than a script argument
you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?– ysth
Jan 25 at 15:31