25

I'm stuck trying to increment a variable in an .xml file. The tag may be in a file 100 times or just twice. I am trying to add a value that will increment the amount several times. I have included some sample code I am working on, but when I run the script it will only place a one and not increment further. Advice would be great on what I'm doing wrong.

for xmlfile in $(find $DIRECTORY -type f -name \*.xml); do
  TFILE="/tmp/$directoryname.$$"
  FROM='><process>'
  TO=' value\=""><process>'
  i=0
  while [ $i -lt 10 ]; do
    i=`expr $i + 1`
    FROM='value\=""'
    TO='value\="'$i'"'
  done
  sed "s/$FROM/$TO/g" "$xmlfile" > $TFILE && mv $TFILE "$xmlfile"
done

The while loop was something I just placed to test the code. It will insert the <process> but it will not insert the increment.

My end goal:

<process>value="1"</process>
<process>value="2"</process>
<process>value="3"</process>
<process>value="4"</process>

And so on as long as <process> is present in the file it needs to increment.

dda
  • 6,030
  • 2
  • 25
  • 34
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127

5 Answers5

36

I just tested your code and it seems to correctly increment i.

You could try changing your increment syntax from:

i=`expr $i + 1`

To

i=$((i+1))
sampson-chen
  • 45,805
  • 12
  • 84
  • 81
  • 15
    or just `(( i++ ))`. Good luck to all. – shellter Nov 14 '12 at 19:56
  • 1
    neither work. Now it prints to .xml file value="10" for everything and does not increment – DᴀʀᴛʜVᴀᴅᴇʀ Nov 14 '12 at 20:02
  • @CuriousGeorge: if you're always getting 10, then: A. where is it getting set to that value (OR are somehow the values from 0-9 are being discarded or skipped), B. how can it even print that when you have a condition that `i -lt 10`, "i lessThan 10" (Maybe you should try `(( i++ < 10 ))`? Learn to turn on the shell debuging/trace feature with `set -vx` near the top and `set +vx` to turn off the trace. This will show you the line (or block) of code that will be executed, and then each executed step with values substituted for the variables. Good luck. – shellter Nov 15 '12 at 01:14
  • @CuriousGeorge: your `while` loop makes sure that `i` is incremented to 10, then you insert that value via `sed`. So yes, that is the expected behavior from your code. – doubleDown Nov 15 '12 at 10:10
21

For a proper increment in bash, use a for loop (C style) :

n=10
for ((i=1; i<=n; i++)) {
    printf '<process>value="%d"</process>\n' $i
}

OUTPUT

<process>value="1"</process>
<process>value="2"</process>
<process>value="3"</process>
<process>value="4"</process>
<process>value="5"</process>
<process>value="6"</process>
<process>value="7"</process>
<process>value="8"</process>
<process>value="9"</process>
<process>value="10"</process>

NOTE

expr is a program used in ancient shell code to do math. In Posix shells like bash, use $(( expression )). In bash and ksh93, you can also use (( expression )) or let expression if you don't need to use the result in an expansion.

EDIT

If I misunderstood your needs and you have a file with blank values like this :

<process>value=""</process>

try this :

$ perl -i -pe '$c++; s/<process>value=""/<process>value"$c"/g' file.xml
<process>value"1"</process>
<process>value"2"</process>
<process>value"3"</process>
<process>value"4"</process>
<process>value"5"</process>
<process>value"6"</process>
<process>value"7"</process>

-i switch edit the file for real, so take care.

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
12

This is the simplest way to increment a variable in bash:

i=0
((++i))
Cory Klein
  • 51,188
  • 43
  • 183
  • 243
  • 4
    when using `set -e`, you should—at least when a zero is the first value (`i=0`)—perform **pre**-increment instead, i.e. `((++i))`. Otherwise your program will stop right at the first increment, because the exit code will be 1. Quite surprising. See https://unix.stackexchange.com/questions/32250/why-does-a-0-let-a-return-exit-code-1 – myrdd Aug 19 '19 at 06:23
4

This also works.

Declaring the variable as an integer.

declare -i i=0

Then later you can increment like so:

i+=1
dskrad
  • 108
  • 8
  • 1
    imho the best answer, since it seems not to have any issues with exit codes [like the increment operator](https://stackoverflow.com/questions/13386223/increment-with-bash#comment101565054_25086041). – myrdd Aug 19 '19 at 06:29
1

Use awk:

awk '{gsub( "value=\"\"", "value=" i++ ); print }' i=1 input-file

This will replace the string value="" with value="1", value="2", etc. You can easily change the start value and the increment ( eg ..."value=" i ); i+=5; print )

William Pursell
  • 204,365
  • 48
  • 270
  • 300