我有一个看起来像这样的字符串
/foo/bar/baz59_ 5stuff.thing
如果最后一个数字大于另一个变量,我想将最后一个数字(示例中为5)增加一个。 9将增加到10。请注意,最后一个数字也可以是多个数字。 “ stuff.thing”也可以是任何东西;除数字外;因此无法对其进行硬编码。
上面的示例将导致/foo/bar/baz59_ 6stuff.thing
我发现了多个问题(和答案),这些问题将从字符串中提取出最后一个数字,并且显然可以将其用于比较。 我遇到的问题是如何确保当我进行替换时,我仅替换了最后一个数字(因为显然我不能仅将“ 5”替换为“ 6”)。有人可以提出任何建议吗?
awk / sed / bash / grep都是可行的。
答案 0 :(得分:7)
更新后的答案
感谢@EdMorton指出对数字超过阈值的进一步要求。可以这样做:
perl -spe 's/(\d+)(?!.*\d+)/$1>$thresh? $1+1 : $1/e' <<< "abc123_456.txt" -- -thresh=500
原始答案
您可以在Perl正则表达式中使用/e
评估/计算替换项。在这里,我只将1添加到捕获的数字串中,但是您可以做更复杂的事情:
perl -pe 's/(\d+)(?!.*\d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt
{希望(?!.*\d+)
是负数,表示没有更多数字。
$1
代表捕获组(\d+)
中捕获的任何数字序列。
请注意,这需要进行修改以处理十进制数字,负数和科学计数法-但这是可能的。
答案 1 :(得分:4)
使用bash正则表达式匹配:
$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]
好的,我们现在有什么?
$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")
所以我们可以构造新的文件名
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
答案 2 :(得分:4)
使用GNU awk将第三个参数匹配():
$ 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
只需将t
设置为您要递增的阈值,例如:
$ 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
答案 3 :(得分:1)
如果它大于脚本参数。
如果我正确理解了它(我假设您正在通过脚本传递参数,并且其值大于字符串的第二个字段数字,然后将1增大到该第二个字段的数字),请您尝试一次。 >
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'
这是我运行script.ksh的示例,它给出以下输出。
/script.ksh 7
/foo/bar/baz59_ 6stuff.thing
答案 4 :(得分:1)
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
修改:
糟糕,我错过了参数要求(如果最后一个数字大于脚本参数,则将最后一个数字增加--一个):
$ 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'
现在输出:
/foo/bar/baz59_ 99stuff.thing
答案 5 :(得分:1)
这是一种较短的gnu awk
方法:
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]
}
然后将其用作:
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
答案 6 :(得分:0)
如果“测试”编号在“绑定”变量中:
perl -pe 'BEGIN{$bound=6} s{(\d+)_(\d+)(?!.*\d+)}{ $i=$2+1;($i>$bound? $1+1:$1)."_".$i}e' <<<"/foo/bar/baz59_5stuff.thing"
/foo/bar/baz59_6stuff.thing