sed increment number

孤者浪人 提交于 2019-12-09 17:40:55

问题


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>
<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>

回答1:


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



回答2:


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.




回答3:


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



回答4:


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.



来源:https://stackoverflow.com/questions/4462954/sed-increment-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!