Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Would you kindly help me to resolve the following?

20066898701..20066901700
20066891201..20066893700
20066879201..20066888700
20009429701..20009439700
20009412201..20009414700

I have an input as above

  1. I need to convert the .. to , seperated

  2. Then the column 2 will be subtracted from column 1 and output to be added with 1

20066898701..20066901700 => (20066901700-20066898701)+1 => 3000

share|improve this question
    
You say "column 2 will be subtracted from column 1" but your example shows column 1 subtracted from column 2. –  Dennis Williamson Nov 9 '10 at 14:22

6 Answers 6

Pipe your output into the following Perl:
perl -ne 'my @fields = split /\s/, $_; foreach my $input (@fields) { if (/^(\d+)..(\d+)$/) { print $2 - $1 + 1, "\n"; } }'

What this does is firstly split the input on spaces (so your first line should work). It then runs a regular expression on each entry to match a string which only contains two numbers separated by .. - the brackets put the numbers in $1 and $2.

For example: echo "20066898701..20066901700" | perl -ne 'my @fields = split /\s/, $_; foreach my $input (@fields) { if (/^(\d+)\.\.(\d+)$/) { print $2 - $1 + 1, "\n"; } }' 3000

share|improve this answer
sed 's/\.\./,/g'<erk|awk 'BEGIN { FS = ","}; { total = ($2 - $1) +1; print total}

Given a file named "erk", containing your data:

tom@holborn:~$  cat erk | sed 's/\.\./,/g'| awk 'BEGIN { FS = ","}; { total = ($2 - $1) +1; print total}'
3000
2500
9500
10000
2500

You could pipe the output of your application straight into sed, instead of cat

share|improve this answer
    
sed is unnecessary. –  jlliagre Nov 9 '10 at 22:22
    
sed is nice, though. –  Tom O'Connor Nov 10 '10 at 10:06
    
Indeed, I meant sed is unnecessary in your code, but I like very much sed nevertheless. –  jlliagre Nov 11 '10 at 14:23
    
I tend to write scripts in left-to-right order, so sed is the most straightforward way to do the first bit, then I think.. Ooh. Awk can do the next bit.. etc etc. –  Tom O'Connor Nov 11 '10 at 14:42

In Bash:

while IFS=. read -r field1 null field2
do
    echo $((field2 - field1 + 1))
done < inputfile
share|improve this answer
for i in 20066898701..20066901700 20066891201..20066893700 20066879201..20066888700 20009429701..20009439700 20009412201..20009414700
do
    echo $i | awk -F "[.]+" '{ printf("%s\n",$2-$1+1); }'
done
3000
2500
9500
10000
2500

If the values are in a single line as it seems now, you can use the simpler:

awk -F "[.]+" '{ printf("%s\n",$2-$1+1); }' filename
share|improve this answer
    
Perhaps your for loop is just for demonstration, but if not it's a very inefficient way to do that. –  Dennis Williamson Nov 9 '10 at 14:21
    
The initial question was showing all values in a single line. It has been edited to show them in multiple lines after my reply. I'm providing a simpler solution now. Of course, launching an awk command for every data pair is highly inefficient but might be "unnoticeably" inefficient if the number of values is not significantly large. –  jlliagre Nov 9 '10 at 15:34

In bash:

cat file-with-numbers.txt | while read i
do
  first=`echo $i | cut -f1 -d.`
  second=`echo $i | cut -f3 -d.`
  expr $second - $first + 1
done
share|improve this answer
perl -pe 's/(\d+)\.\.(\d+)$/sprintf "%d,%d,%d",$1,$2,($2-$1)+1/eg;' filename

or

perl -pe 's/(\d+)\.\.(\d+)$/($2-$1)+1/eg;' filename  

if you only want the difference

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.