Подтвердить что ты не робот

Поиск пробелов последовательных номеров

Я не делаю этого для жизни, поэтому простите меня, если это простой вопрос (или более сложный, чем я думаю). Я копал в архивах и нашел множество советов, которые близки, но являюсь новичком. Я не уверен, как подстраиваться под мои потребности, или они намного превосходят мое понимание.

У меня есть несколько больших файлов данных, которые я могу проанализировать для создания списка координат, которые в основном являются последовательными

5
6
7
8
15
16
17
25
26
27

То, что я хочу, это список пробелов

1-4
9-14
18-24

Я не знаю perl, SQL или что-то необычное, но думал, что смогу сделать что-то, что вычитает одно число из следующего. Я мог бы по крайней мере grep вывести, где разница не была 1 или -1 и работать с этим, чтобы получить пробелы.

4b9b3361

Ответ 1

С :

awk '$1!=p+1{print p+1"-"$1-1}{p=$1}' file.txt

объяснения

  • $1 - это первый столбец из текущей строки ввода
  • p - это предыдущее значение последней строки
  • поэтому ($1!=p+1) является условием: если $1 отличается от предыдущего значения +1, то:
  • эта часть выполнена: {print p+1 "-" $1-1}: напечатать предыдущее значение +1, символ - и первые столбцы + 1
  • {p=$1} выполняется для каждой строки: p присваивается текущему 1-му столбцу

Ответ 2

Просто запомните предыдущее число и убедитесь, что текущий - предыдущий плюс один:

#! /bin/bash
previous=0
while read n ; do
    if (( n != previous + 1 )) ; then
        echo $(( previous + 1 ))-$(( n - 1 ))
    fi
    previous=$n
done

Вам может потребоваться добавить некоторую проверку, чтобы предотвратить такие строки, как 28-28 для пробелов в одном пробеле.

Ответ 3

Ответ на Ruby

Возможно, кто-то еще может предоставить вам решение Bash или Awk, о котором вы просили. Тем не менее, я думаю, что любой ответ на основе оболочки, скорее всего, будет крайне локализован для вашего набора данных и не очень расширяем. Решение проблемы в Ruby довольно простое и обеспечивает гибкое форматирование и дополнительные возможности для управления набором данных другими способами по дороге. YMMV.

#!/usr/bin/env ruby

# You could read from a file if you prefer,
# but this is your provided corpus. 
nums = [5, 6, 7, 8, 15, 16, 17, 25, 26, 27]

# Find gaps between zero and first digit.
nums.unshift 0

# Create array of arrays containing missing digits.
missing_nums = nums.each_cons(2).map do |array|
                 (array.first.succ...array.last).to_a unless
                  array.first.succ == array.last
               end.compact
# => [[1, 2, 3, 4], [9, 10, 11, 12, 13, 14], [18, 19, 20, 21, 22, 23, 24]]

# Format the results any way you want.
puts missing_nums.map { |ary| "#{ary.first}-#{ary.last}" }

Учитывая ваш текущий корпус, на стандартном выходе получается следующее:

1-4
9-14
18-24

Ответ 4

интересный вопрос.

sputnick awk one-liner хорош. Я не могу написать более простой, чем его. Я просто добавляю другой способ, используя diff:

 seq $(tail -1 file)|diff - file|grep -Po '.*(?=d)'

вывод с вашим примером будет:

1,4
9,14
18,24

Я знал, что в нем есть запятая вместо -. вы можете заменить grep на sed, чтобы получить -, grep не может изменить текст ввода... но идея такая же.

надеюсь, что это поможет.

Ответ 5

Решение Perl аналогично решению awk от StardustOne:

perl -ane 'if ($F[0] != $p+1) {printf "%d-%d\n",$p+1,$F[0]-1}; $p=$F[0]' file.txt

Эти параметры командной строки используются:

  • -n перемещаться по каждой строке входного файла, не печатать автоматически каждую строку

  • -a режим автосплит - разделение входных строк на массив @F. По умолчанию разбивается на пробелы. Поля индексируются начиная с 0.

  • -e выполнить код perl