开发者

sed increment number

开发者 https://www.devze.com 2023-01-31 11:44 出处:网络
I\'d like to substitute some text with an incremental value. Considering file xx: <outro>dfdfd</outro>

I'd like to substitute some text with an incremental value. Considering file xx:

<outro>dfdfd</outro>
<RecordID>1</RecordID>
<outro>dfdfd</outro>
<RecordID>1</RecordID>
<outro>dfdfd</outro>
<RecordID>1</RecordID>开发者_C百科
<outro>dfdfd</outro>

and sed command:

for n in seq 3;do sed -e 's/<RecordID>\d/<RecordID>'`echo $n`'/' xx; done

the echo $n command does not get incremented.

Tryed also:

n=1; sed -e 's/<RecordID>/<RecordID>'`echo $n ;let n=$n+1`'/g' xx

but with no success.

Considering only sed (no awk or perl) how can I have the RecordID field incremented as in:

<outro>dfdfd</outro>
<RecordID>1</RecordID>
<outro>dfdfd</outro>
<RecordID>2</RecordID>
<outro>dfdfd</outro>
<RecordID>3</RecordID>
<outro>dfdfd</outro>


while read line; do n=$((++n)) &&  echo $line|sed -e 's/[0-9]/'$(($n))'/' ; done < patt


Notwithstanding the statement in the question that Perl and Awk cannot be used, the answers given so far demonstrate that sed is not the correct tool for this task. Both the answers I see only work with an extremely limited set of data and only work sanely on extremely small sets of data.

Using sed, there isn't a sensible method available to deal with thousands of records. You can hack solutions together, if you're careful, that deal with three record IDs (hint: you might need to map 3 to 4 before you map 2 to 3, lest the mapped 3 be remapped to 4).

Using Perl or Python, it is doable.

perl -e 's{<RecordID>(\d+)</RecordID>}{$n=$n+1; "<RecordID>$n</RecordID>"}e'

This is very much a case of 'use the right tool for the job'. sed is a great tool for the jobs for which it is designed (and a good many for which it was not designed). However, this is over-stressing it.


First, sed doesn't understand \d. Use [0-9] or [[:digit:]] instead.

Second, for n in seq 3 will set n to "seq" and "3". Use for n in $(seq 3) or (in Bash) use for n in {1..3}.

Third, you need to save the result of your replacement. If your version of sed supports -i (in-place), you can use that or you might need to use sed ... xx > xx.tmp && mv xx.tmp xx.

Fourth, you need to select which line to make the change to.

Put all that together and this works, but could be quite slow:

for n in $(seq 3); do sed -e $(($n*2))'s/<RecordID>[[:digit:]]/<RecordID>'$n'/' xx > xx.tmp && mv xx.tmp xx; done


The true way to do this with sed is of course to obviate the need for looping in the shell. Use something like Denis' address matcher to narrow down the scope, then use the expressions from the script in sed's info pages. It lexically increments numbers, no arithmetic involved. The sole trick it does is to care for the carry.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号