Convert list of numbers to text range


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Convert list of numbers to text range
# 1  
Old 12-14-2016
Convert list of numbers to text range

Hi,

I'd like to take a list of numbers (with a prefix) and convert to a range, for example:

Code:
cn001
cn004
cn016
cn017
cn018
cn019
cn020
cn021
cn031
cn032
cn038
cn042
cn043
cn044
cn045

What I'd like is to reduce this down to the following (it's slurm output!):

Code:
cn[001,004,016-021,031-032,038,042-045]

Cheers,

Chris
# 2  
Old 12-14-2016
Dear chrissycc,

I have a few to questions pose in response first:-
  • Is this homework/assignment? There are specific forums for these.
  • What have you tried so far?
  • What output/errors do you get?
  • What OS and version are you using?
  • What are your preferred tools? (C, shell, perl, awk, etc.)
  • What logical process have you considered? (to help steer us to follow what you are trying to achieve)
Most importantly, What have you tried so far?

There are probably many ways to achieve most tasks, so giving us an idea of your style and thoughts will help us guide you to an answer most suitable to you so you can adjust it to suit your needs in future.


We're all here to learn and getting the relevant information will help us all.


Kind regards,
Robin
# 3  
Old 12-14-2016
Ok, apologies....

Not homework/assignment, just a task I want to complete at work to make reporting on some Slurm scheduler output a bit more manageable.

CentOS 7, awk the tool of choice.

I have tried the following, which seems to be getting somewhere, just having a mental block on how to get over the finishing line:

Code:
cat test | sed 's/cn//g' | \
awk '{ \
if (length(PRE) == 0)  printf "%s", $1 ; \
else if ($1>PRE+1) printf ",%s", $1 ; \
else if ($1=PRE+1) printf "-" ; \
PRE=$1 ; } \
END { print }'

Producing:

Code:
001,004,016-----,031-,038,042---,048048

(I put an additional cn048 at the end, just as a test as I got some weird output of another test batch of data using this technique. Otherwise it is the data above).

Cheers,

Chris
# 4  
Old 12-14-2016
How about
Code:
awk '
NR == 1         {PFX = substr ($1, 1, match ($1, /[0-9]/)-1)
                 printf "%s[", PFX
                 LEN = length($1) - length(PFX)
                 PRE = -1E9 
                }

                {sub (PFX, "")
                }

$1 == PRE + 1   {SEQ = 1
                }
$1  > PRE + 1   {if (SEQ) printf "-%0*d", LEN, PRE
                 printf "%s%0*d", DL, LEN, $1
                 DL = ","
                 SEQ = 0
                }

                {PRE = $1
                }

END             {printf "-%0*d]\n", LEN, $1
                }
' file
cn[001,004,016-021,031-032,038,042-045]

This User Gave Thanks to RudiC For This Post:
# 5  
Old 12-16-2016
Hi RudiC - thanks that is almost perfect.....

The almost comes in as if I have a slightly different dataset where the final number isn't the end of a sequence, it becomes a sequence of its own, e.g.

Input:
Code:
cn001
cn004
cn016
cn017
cn018
cn019
cn020
cn021
cn031
cn032
cn038
cn042
cn043
cn044
cn045
cn048

Output:
Code:
cn[001,004,016-021,031-032,038,042-045,048-048]

I'm guessing I just need to drop an if statement in after END, so I'll have a look at that and report back....

---------- Post updated 16-12-16 at 09:25 AM ---------- Previous update was 15-12-16 at 11:15 AM ----------

Thanks for the help RudiC. My final code which seems to work (I've run it through various test cases):

Code:
awk '
NR == 1         {PFX = substr ($1, 1, match ($1, /[0-9]/)-1)
                 printf "%s[", PFX
                 LEN = length($1) - length(PFX)
                 PRE = -1E9 
                }

                {sub (PFX, "")
                }

$1 == PRE + 1   {SEQ = 1
                }
$1  > PRE + 1   {if (SEQ) printf "-%0*d", LEN, PRE
                 printf "%s%0*d", DL, LEN, $1
                 DL = ","
                 SEQ = 0
                }

                { PREPRE=PRE ; PRE = $1 }
END          { 
                  if ($1 > PREPRE+1) { printf "]\n" }
                  else { printf "-%0*d]\n", LEN, $1 }
                }
' file

# 6  
Old 12-16-2016
Glad it works. How about this somewhat shorter approach:
Code:
END		{if (SEQ) printf "-%0*d", LEN, $1
		 printf "]\n"
                }

This User Gave Thanks to RudiC For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Shell script to convert IP range csv into a list of single IP's

Hi All, I am looking for some help to convert a csv with IP ranges in.. in the format e.g. 1.1.1.2, 1.1.1.5 2.1.1.10, 2.1.1.20 and would be looking to output as follows: 1.1.1.2 1.1.1.3 1.1.1.4 1.1.1.5 2.1.1.10 2.1.1.11 etc etc up to 2.1.1.20 I have tried a few google... (4 Replies)
Discussion started by: zippyzip
4 Replies

2. Shell Programming and Scripting

Print range of numbers

Hi I am getting an argument which specifies the range of numbers. eg: 7-15 Is there a way that i can easily (avoiding loop) print the range of number between and including the specified above. The above example should translate to 7,8,9,10,11,12,13,14,15 (3 Replies)
Discussion started by: tostay2003
3 Replies

3. Shell Programming and Scripting

Match on a range of numbers

Hi, I'm trying to match a filename that could be called anything from vout001 to vout252 and was trying to do a small test but I'm not getting the result I thought I would.. Can some one tell me what I'm doing wrong? *****@********>echo $mynumber ... (4 Replies)
Discussion started by: Jazmania
4 Replies

4. Shell Programming and Scripting

grep for a range of numbers

Dear Friends, I want to know how to grep for the lines that has a number between given range(start and end). I have tried the following sed command. sed -n -e '/20030101011442/,/20030101035519/p' However this requires both start and end to be part of the content being grepped. However... (4 Replies)
Discussion started by: tamil.pamaran
4 Replies

5. UNIX for Dummies Questions & Answers

How to count how many numbers in a certain range?

Hi I have a data file with two columns which looks like: 1 42 2 40 3 55 4 50 5 38 6 49 7 33 8 46 9 39 10 33 11 33 12 26 13 46 14 44 15 55 16 54 17 30 18 32 (7 Replies)
Discussion started by: marhuu
7 Replies

6. Shell Programming and Scripting

Convert perl qw list to text file list?

Does anyone have a good example? I am having trouble looping.. Thanks (1 Reply)
Discussion started by: mrlayance
1 Replies

7. UNIX for Dummies Questions & Answers

List-to-Range of Numbers

Hello, I have two columns with data that look like this: Col1 Col2 ------ ----- a 1 a 2 a 3 a 4 a 7 a 8 a 9 a 10 a 11 b 6 b 7 b 8 b 9 b 14 (5 Replies)
Discussion started by: Gussifinknottle
5 Replies

8. Shell Programming and Scripting

read numbers from file and output which numbers belongs to which range

Howdy experts, We have some ranges of number which belongs to particual group as below. GroupNo StartRange EndRange Group0125 935300 935399 Group2006 935400 935476 937430 937459 Group0324 935477 935549 ... (6 Replies)
Discussion started by: thepurple
6 Replies

9. Shell Programming and Scripting

Inserting a range of consecutive numbers into a text file

I have a text file in the following format .... START 1,1 2,1 3,1 .. .. 9,1 10,1 END .... I want to change to the output to .... START 1,1 2,1 3,1 .. (4 Replies)
Discussion started by: VNR
4 Replies

10. Shell Programming and Scripting

grep numbers range

I want to grep a range of numbers in a log file. My log file looks like this: 20050807070609Z;blah blah That is a combination of yr,month,date,hours,minutes,seconds. I want to search in the log file events that happened between a particular time. like between 20050807070000 to 20050822070000... (1 Reply)
Discussion started by: azmathshaikh
1 Replies
Login or Register to Ask a Question