LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 11-14-2012, 09:10 AM   #1
graphicsmanx1
Member
 
Registered: Oct 2012
Posts: 81

Rep: Reputation: Disabled
Increment in bash


Im trying to figure out how to increment in bash. I know Java is 1++ but what is it in bash and how does the loop look? Im trying to increment and echo the number to an XML file. As long as there is a certain tag there I want each tag to have a value added.

Example of what code needs to do:
Code:
BEFORE:
<value></value>
<value></value>
<value></value>
<value></value>

AFTER:
<value>1</value>
<value>3</value>
<value>4</value>
<value>5</value>
 
Old 11-14-2012, 09:25 AM   #2
evgenyz
Member
 
Registered: Sep 2012
Posts: 48

Rep: Reputation: Disabled
#!/bin/bash
# just an example
i=0
while [ $i -lt 10 ]; do
i=`expr $i + 1`
echo "<value>$i</value>
done
 
2 members found this post helpful.
Old 11-14-2012, 09:34 AM   #3
graphicsmanx1
Member
 
Registered: Oct 2012
Posts: 81

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by evgenyz View Post
#!/bin/bash
# just an example
i=0
while [ $i -lt 10 ]; do
i=`expr $i + 1`
echo "<value>$i</value>
done
I do understand your variable setting and echo.

I see you are using -lt which means less than 10 but I would not know the value so I need it to be infinite as long as there is a <value> so what is best?

What does the expr mean and I assume by your + 1 is the increment expression needed?
 
Old 11-14-2012, 09:47 AM   #4
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,524
Blog Entries: 27

Rep: Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175
It can be done in pure bash without having to run an external command such as expr:
Code:
c@CW9:~$ i=1
c@CW9:~$ ((i++))
c@CW9:~$ echo $i
2
 
1 members found this post helpful.
Old 11-14-2012, 10:04 AM   #5
H_TeXMeX_H
Guru
 
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,928
Blog Entries: 2

Rep: Reputation: 1269Reputation: 1269Reputation: 1269Reputation: 1269Reputation: 1269Reputation: 1269Reputation: 1269Reputation: 1269Reputation: 1269
There are many ways to do it:

Code:
for i in $(seq 1 5)
do

done
Just incrementing:
Code:
# these are bash only
let i++
((i++))
# these are more portable
i=$(($i+1))
i=$(expr $i + 1)
 
2 members found this post helpful.
Old 11-14-2012, 10:12 AM   #6
evgenyz
Member
 
Registered: Sep 2012
Posts: 48

Rep: Reputation: Disabled
You can replace above while loop (and the way you increment the value, thanks to catkin!) by following hypotetical script:

#!/bin/bash
# just an example
i=0
while read line
do
((i++))
# Do some processing with $line for example
echo "<value>$i</value>"
done < file
 
Old 11-14-2012, 10:56 AM   #7
graphicsmanx1
Member
 
Registered: Oct 2012
Posts: 81

Original Poster
Rep: Reputation: Disabled
ya now I can get it to echo to the file but it will echo all 1s and not numerical

Last edited by graphicsmanx1; 11-14-2012 at 12:23 PM.
 
Old 11-14-2012, 07:06 PM   #8
wolverene13
Member
 
Registered: May 2010
Location: Matiland, FL
Distribution: Debian Squeeze
Posts: 49

Rep: Reputation: 0
Quote:
Originally Posted by graphicsmanx1 View Post
Im trying to figure out how to increment in bash. I know Java is 1++ but what is it in bash and how does the loop look? Im trying to increment and echo the number to an XML file. As long as there is a certain tag there I want each tag to have a value added.

Example of what code needs to do:
Code:
BEFORE:
<value></value>
<value></value>
<value></value>
<value></value>

AFTER:
<value>1</value>
<value>3</value>
<value>4</value>
<value>5</value>
Try this:

Code:
for ((i,i>=1,i++))
do
echo "<value>$i</value>"
done

Last edited by wolverene13; 11-14-2012 at 07:07 PM. Reason: forgot code tags
 
Old 11-14-2012, 07:09 PM   #9
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,524
Blog Entries: 27

Rep: Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175
Quote:
Originally Posted by graphicsmanx1 View Post
ya now I can get it to echo to the file but it will echo all 1s and not numerical
Can you post your script and show the result of running it?
 
Old 11-14-2012, 07:26 PM   #10
wolverene13
Member
 
Registered: May 2010
Location: Matiland, FL
Distribution: Debian Squeeze
Posts: 49

Rep: Reputation: 0
Better way than before

Quote:
Originally Posted by graphicsmanx1 View Post
Im trying to figure out how to increment in bash. I know Java is 1++ but what is it in bash and how does the loop look? Im trying to increment and echo the number to an XML file. As long as there is a certain tag there I want each tag to have a value added.

Example of what code needs to do:
Code:
BEFORE:
<value></value>
<value></value>
<value></value>
<value></value>

AFTER:
<value>1</value>
<value>3</value>
<value>4</value>
<value>5</value>
Nevermind, disregard my last solution. After re-reading, I see what you mean. Try this:

Code:
linenum=$(cat file.txt | wc -l)
numval=0

while [ $numval -lt $linenum ]
do
echo "<value>$numval</value>"
numval=`expr $numval + 1`
done

Last edited by wolverene13; 11-14-2012 at 07:39 PM. Reason: left $ where it shouldn't be
 
Old 11-15-2012, 09:02 AM   #11
graphicsmanx1
Member
 
Registered: Oct 2012
Posts: 81

Original Poster
Rep: Reputation: Disabled
is there a way to count the <value></value> tag and then add 1 with an incremental of 1 to each line till all the values are correct. I understand the loop and I understand now how to increment four different ways. However that still doesn't solve my issue.

code Im playing with:
Code:
for xmlfile in $(find $DIRECTORY -type f -name \*.xml); do
	TFILE="/tmp/$directoryname.$$"
	
	FROM='><process>'
	TO=' value\=""><process>'	
	i=1
	while [ $i -eq 1 ]; do
		i=`expr $i + 1`
		FROM='value\=""'
		TO='value\="'$i'"'	
	done
	sed "s/$FROM/$TO/g" "$xmlfile" > $TFILE && mv $TFILE "$xmlfile"
done
now what happens is it will go in an infinte loop in the terminal. Im missing something in the while loop that will count the value="" and increment accordingly.

So if I have 20 <process></process> it will add in return do this:
PART 1
Code:
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
<process>value=""</process>
PART 2
Code:
<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>
<process>value="11"</process>
<process>value="12"</process>
<process>value="13"</process>
<process>value="14"</process>
<process>value="15"</process>
<process>value="16"</process>
<process>value="17"</process>
<process>value="18"</process>
<process>value="19"</process>
<process>value="20"</process>
if I add a -lt than 10 it will count to 10 and do this:
Code:
<process>value="10"</process>
<process>value="10"</process>
<process>value="10"</process>
<process>value="10"</process>
NOTE I DONT NEED A LESS THAN 10 BUT IT WAS SOMETHING I WAS TESTING

Last edited by graphicsmanx1; 11-15-2012 at 09:06 AM.
 
Old 11-15-2012, 10:18 AM   #12
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,524
Blog Entries: 27

Rep: Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175
How about this?
Code:
#!/bin/bash

dir=/tmp

while IFS= read -r -d '' file
do
    i=1 
    while IFS= read -r -u 3 line
    do
        if [[ $line = '<process></process>' ]]; then
           echo "<process>value=\"$((i++))\"</process>"
        else
           echo "$line"
        fi  
    done 3< "$file" > "$file.done"
done < <(find $dir -type f -name \*.xml -print0)
The outer loop is the standard idiom for robustly looping on file names. It is explained in this LQ post

The inner loop uses file descriptor 3 because stdin (file descriptor 1) is already in use by the outer loop.

EDIT: fixed missing / in <process><process>

Last edited by catkin; 11-15-2012 at 10:24 AM.
 
Old 11-15-2012, 11:32 AM   #13
graphicsmanx1
Member
 
Registered: Oct 2012
Posts: 81

Original Poster
Rep: Reputation: Disabled
I do not understand what you are doing.

EDIT:

ok from the reading I get that this is creating an empty string:
Code:
while IFS= read -r -d '' file
simple variable declaration:
Code:
i=1
im lost with the file descriptor 3. Is that what is creating the variable $line???

also what is the meaning of this?
Code:
3< "$file" > "$file.done"
this line always throws me:
Quote:
< <(find $dir -type f -name \*.xml -print0)
I think you posted it before but the <() and -print0 im confused with the process

ok
read -r: do not allow backslashes
read -u: read from file descriptor

Last edited by graphicsmanx1; 11-15-2012 at 12:32 PM.
 
Old 11-15-2012, 03:05 PM   #14
graphicsmanx1
Member
 
Registered: Oct 2012
Posts: 81

Original Poster
Rep: Reputation: Disabled
also I think I have confused many with my question. My issue in general is NOT the increment BUT how to add the increment to the file. I do thank many of you because I have learned several variations of how to do the increment.
 
Old 11-15-2012, 08:26 PM   #15
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,524
Blog Entries: 27

Rep: Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175Reputation: 1175
Thanks for your questions.
Quote:
Originally Posted by graphicsmanx1 View Post
ok from the reading I get that this is creating an empty string:
Code:
while IFS= read -r -d '' file
It reads ASCII NUL delimited file names into variable file from the while; do ... ; done loop input (which is generated by the find command).
Quote:
Originally Posted by graphicsmanx1 View Post
im lost with the file descriptor 3. Is that what is creating the variable $line???

also what is the meaning of this?
Code:
3< "$file" > "$file.done"
It is the read command in while IFS= read -r -u 3 line that assigns values to the variable line. That read command is reading from file $file. 3< "$file" sets up file descriptor (a.k.a unit) 3 as the input to the inner loop. It is a "input redirect". Similarly > "$file.done" redirects standard output (stdout) from the inner while; do ... ; done file to file "$file.done". Thus the echo commands in the inner loop write to file "$file.done".
Quote:
Originally Posted by graphicsmanx1 View Post
this line always throws me:
Code:
< <(find $dir -type f -name \*.xml -print0)
The <( ... ) is process substitution. It writes the output of the find command to a temporary file. The < before it is an input redirect making the standard input (stdin) of the outer loop that temporary file. The overall effect is to send the output of the find command to the outer loop. The only command that reads from stdin within the outer loop is the read command in while IFS= read -r -d '' file. The -print0 makes the find command separate the file names it outputs with ASCII NULs instead of the default newlines. ASCII NUL is a 0, hence the 0 in -print0. The purpose is to work with file names that include newlines.

Last edited by catkin; 11-15-2012 at 08:42 PM. Reason: Moved ASCII NUL links to first occurrence
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[bash/awk] How to increment hour in a loop? wasim_jd Linux - Newbie 4 12-08-2011 11:59 AM
Bash shell script: Str(007) to int(7),increment it(8) & convert back to string(008) drwatson_droid Programming 5 12-01-2011 10:44 AM
how to increment the date in a file name via bash script tensigh Programming 10 07-23-2010 03:49 AM
[Bash] increment number in a string czezz Programming 4 07-01-2009 11:34 AM
bash equivalent to C increment operator andrewb758 Linux - General 5 02-21-2009 12:25 PM


All times are GMT -5. The time now is 03:39 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration