LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 07-09-2015, 08:19 AM   #1
kingston
Member
 
Registered: Mar 2008
Location: Bengaluru, India
Distribution: RHEL 5.5, Solaris 5.10
Posts: 215
Blog Entries: 1

Rep: Reputation: 21
Bash Script to add numbers which has 0 prefix


Hi Guru's

I have to write a bash script which has requirement as follows. Can someone help me?

Input:

015
009

Output:

009
010
011
012
013
014
015

To be precise, when i give inputs as follows, the script should give an output as

kingston-vm-009
kingston-vm-010
kingston-vm-011
kingston-vm-012
kingston-vm-013
kingston-vm-014
kingston-vm-015

I tried couple of combinations to add/subtract using "bc" and "expr". But didn't get succeeded.

Thanks in Advance.

Regards

Kingston S
 
Old 07-09-2015, 08:23 AM   #2
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,888

Rep: Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317Reputation: 7317
would be nice to see what has you really tried
 
Old 07-09-2015, 08:54 AM   #3
kingston
Member
 
Registered: Mar 2008
Location: Bengaluru, India
Distribution: RHEL 5.5, Solaris 5.10
Posts: 215

Original Poster
Blog Entries: 1

Rep: Reputation: 21
Script is as follows

#!/bin/bash
FN=king-ston-vm-005
LN=king-ston-vm-008
FN_N=`echo $FN |awk -F "vm-" '{print $2}'`
echo $FN_N
LN_N=`echo $LN |awk -F "vm-" '{print $2}'`
echo $LN_N
TN_N=`bc<<<$LN_N-$FN_N`
TN_N_1=`expr 1 + $TN_N`
echo -e "Total No Nodes : $TN_N_1"


FN1=`echo $FN |awk -F "-" '{print $1"-"$2"-"$3"-"}'`
LN1=`echo $LN |awk -F "-" '{print $1"-"$2"-"$3"-"}'`
#echo $FN1
#echo $LN1

c=$FN_N
d=1
while [ $c -le $LN_N ]
do
host="$FN1$FN_N"
echo -e "Node$d : $host"
c=$(($c+1))
d=$(($d+1))
done

Output is :

[kvedanay@one scripts]$ ./test1
005
008
Total No Nodes : 4
Node1 : king-ston-vm-005
Node2 : king-ston-vm-005
Node3 : king-ston-vm-005
Node4 : king-ston-vm-005

Expected output is :

005
008
Total No Nodes : 4
Node1 : king-ston-vm-005
Node2 : king-ston-vm-006
Node3 : king-ston-vm-007
Node4 : king-ston-vm-008

Regards

Kingston S
 
Old 07-09-2015, 09:08 AM   #4
Ser Olmy
Senior Member
 
Registered: Jan 2012
Distribution: Slackware
Posts: 3,341

Rep: Reputation: Disabled
Please put your scripts/code inside [code][/code] tags, as that greatly improves readability by preserving whitespace and indentation.

Here's some information that you may find useful:
  1. To prevent numbers with leading zeros from being interpreted as octal by bash, prefix them with 10#, which means "the following number is in base 10". For instance, echo $((010 + 1)) will produce 9 as octal "10" is 8 in decimal, while echo $((10#010 + 1)) returns 11.
  2. To print integers prefixed with a specific number of zeros, use printf (for instance, printf "%04d%s" $a will add up to three zeros, ensuring that $a is at least 4 digits long)
 
1 members found this post helpful.
Old 07-09-2015, 10:22 PM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
In addition I would suggest looking at parameter expansion and for loops. There should be no reason to call on external commands such as awk.
 
Old 07-10-2015, 01:34 AM   #6
berndbausch
LQ Addict
 
Registered: Nov 2013
Location: Tokyo
Distribution: Mostly Ubuntu and Centos
Posts: 6,316

Rep: Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002
The seq command might be an alternative. It doesn't interpret leading zeroes as octal. Unfortunately it doesn't print them, so you have to add the leading zeroes back in.

Last edited by berndbausch; 07-10-2015 at 01:41 AM.
 
Old 07-10-2015, 01:56 AM   #7
HMW
Member
 
Registered: Aug 2013
Location: Sweden
Distribution: Debian, Arch, Red Hat, CentOS
Posts: 773
Blog Entries: 3

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
Here is how you can loop using the arguments passed to your script. Note that you can NOT use $1 and $2 directly, this:
Code:
for i in {$1..$2}
...will NOT work.

But this works:
Code:
#!/bin/bash

BEGIN=$1
END=$2

for ((i=$BEGIN; i<=$END; i++)); do
    printf "%03d%s\n" $i
done
Here's the output:
Code:
./for_loop.sh 6 12
006
007
008
009
010
011
012
Also, this:
Quote:
Originally Posted by Ser Olmy
To prevent numbers with leading zeros from being interpreted as octal by bash, prefix them with 10#, which means "the following number is in base 10". For instance, echo $((010 + 1)) will produce 9 as octal "10" is 8 in decimal, while echo $((10#010 + 1)) returns 11.
...is very useful information. Thanks!
 
Old 07-10-2015, 02:01 AM   #8
HMW
Member
 
Registered: Aug 2013
Location: Sweden
Distribution: Debian, Arch, Red Hat, CentOS
Posts: 773
Blog Entries: 3

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
Quote:
Originally Posted by berndbausch View Post
The seq command might be an alternative. It doesn't interpret leading zeroes as octal. Unfortunately it doesn't print them, so you have to add the leading zeroes back in.
That depends...

Code:
for num in $(seq -w 01 10); do echo $num; done
01
02
03
04
05
06
07
08
09
10
 
Old 07-10-2015, 03:19 AM   #9
berndbausch
LQ Addict
 
Registered: Nov 2013
Location: Tokyo
Distribution: Mostly Ubuntu and Centos
Posts: 6,316

Rep: Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002Reputation: 2002
Quote:
Originally Posted by HMW View Post
That depends...

Code:
for num in $(seq -w 01 10); do echo $num; done
01
02
03...
I somehow missed the -w option. Thanks for correcting me! Seems that this is the easiest solution.
 
Old 07-10-2015, 04:26 AM   #10
HMW
Member
 
Registered: Aug 2013
Location: Sweden
Distribution: Debian, Arch, Red Hat, CentOS
Posts: 773
Blog Entries: 3

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
Quote:
Originally Posted by berndbausch View Post
I somehow missed the -w option. Thanks for correcting me! Seems that this is the easiest solution.
Not in this case, since we are dealing with two leading zeroes. seq is not useful for that:
Code:
seq -w 001 10
01
02
03
04
05
06
07
08
09
10
printf is probably the best solution.

Best regards,
HMW
 
Old 07-10-2015, 06:45 AM   #11
Shadow_7
Senior Member
 
Registered: Feb 2003
Distribution: debian
Posts: 4,137
Blog Entries: 1

Rep: Reputation: 874Reputation: 874Reputation: 874Reputation: 874Reputation: 874Reputation: 874Reputation: 874
printf is probably better, but you can treat the number (without leading zeroes) as a string. And concatenate it with a bunch of leading zeroes, and tail the length of string you wish to use.

Code:
for COUNT in 1 2 3 4 5 6 7
do
  STRING="0000000"$COUNT
  USEFUL=$(cat $STRING | tail -c 4)
  echo $USEFUL
done
But that's quirky as various versions of tail might be -c 4 or -c 3 for a 3 digit output. There's also length syntax and substring syntaxes built into bash that can do much of the same stuff in less intuitive ways. Which will fail if said script is not run under bash as not all distros default to bash and if you run the script with "sh script.sh" instead of "./script.sh" it will use that other default shell. Which might be dash for distros like debian which lacks those length and substring extras (or uses a different syntax).

Last edited by Shadow_7; 07-10-2015 at 06:51 AM.
 
Old 07-10-2015, 08:11 AM   #12
kingston
Member
 
Registered: Mar 2008
Location: Bengaluru, India
Distribution: RHEL 5.5, Solaris 5.10
Posts: 215

Original Poster
Blog Entries: 1

Rep: Reputation: 21
Hi HMW

Your solution almost worked. But it is not working, when the second argument was given with the "0" prefix.
Can you have a look?

Code:
[kingston@one scripts]$ ./test2 002 12
002
003
004
005
006
007
008
009
010
011
012
[kingston@one scripts]$ ./test2 002 012
002
003
004
005
006
007
008
009
010
Regards

Kingston S
 
Old 07-10-2015, 09:04 AM   #13
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
Personally I would just strip the leading zeroes as well, seeing the original string contains other characters.
Code:
#!/usr/bin/env bash

FN=king-ston-vm-005
LN=king-ston-vm-008

start=${FN##*0}
end=${LN##*0}

for (( ind = start; ind <= end; ind++ ))
do
	printf "03d\n" "$ind"
done
 
1 members found this post helpful.
Old 07-10-2015, 09:07 AM   #14
HMW
Member
 
Registered: Aug 2013
Location: Sweden
Distribution: Debian, Arch, Red Hat, CentOS
Posts: 773
Blog Entries: 3

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
Quote:
Originally Posted by kingston View Post
Hi HMW

Your solution almost worked. But it is not working, when the second argument was given with the "0" prefix.
Can you have a look?
Ah! I didn't realize that you sent the leading zeroes in as arguments. I should have read more carefully.

Ok, it's the octal thingy again causing trouble. If it were me, I would strip the arguments ($1 and $2) of leading zeroes, and then use the loop.

Like this:
Code:
echo "012" | sed 's/^00\?//'
12

echo "002" | sed 's/^00\?//'
2
This regex also leaves the "proper" three-digit numbers untouched:
Code:
echo "135" | sed 's/^00\?//'
135
So, my solution (which may be a bit backward, but at least it seems to work now) is:
Code:
#!/bin/bash

BEGIN=$(echo $1 | sed 's/^00\?//')
END=$(echo $2 | sed 's/^00\?//')

for ((i=$BEGIN; i<=$END; i++)); do
    printf "03ds\n" $i
done
Examples:
Code:
./leading_zeroes.sh 002 012
002
003
004
005
006
007
008
009
010
011
012
Code:
./leading_zeroes.sh 089 100
089
090
091
092
093
094
095
096
097
098
099
100
Code:
./leading_zeroes.sh 1 3
001
002
003
As you can see from the above, you can now pass the arguments both WITH leading zeroes and without, and it will still work.

Best regards,
HMW

Edit: I see that Grail beat me to it. And as you can see doesn't use sed, take your pick!

Last edited by HMW; 07-10-2015 at 09:11 AM.
 
Old 07-18-2015, 11:45 AM   #15
kingston
Member
 
Registered: Mar 2008
Location: Bengaluru, India
Distribution: RHEL 5.5, Solaris 5.10
Posts: 215

Original Poster
Blog Entries: 1

Rep: Reputation: 21
Thanks everyone. Special thanks to HMW and Grail. Your solution is the one I was looking for.
Started building rest part of my script.

Before resolving this thread, I would like to highlight the following (sorry, I couldn't explain)

Following printf command didn't work

Code:
printf "03ds\n" $I
But this one is working fine
Code:
printf "%03d%s\n" $I
 
  


Reply



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
how to add numbers in a formatted file via a bash script? zero79 Linux - General 8 12-24-2010 05:48 PM
[SOLVED] Script to add up numbers in textfile philipz Programming 3 05-20-2010 08:38 AM
how to extract paragraphs from file in BASH script followed by prefix ! , !! and !!! nabmufti Programming 4 02-10-2008 09:23 AM
Bash + How to add Hexadecimal numbers trscookie Programming 7 09-03-2007 04:22 PM
Bash script: add all numbers from command output wi-Z-art Programming 2 08-06-2003 09:16 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 09:33 PM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration