37

我不是为了谋生而做这些事情,所以如果这是一个简单的问题(或者比我想象的更复杂),请原谅我。我一直在挖掘档案,发现了很多很接近的技巧,但作为一个新手,我不确定如何根据自己的需要进行调整,或者它们超出了我的理解范围。

我有一些大型数据文件,我可以解析出来以生成一个大部分是顺序的坐标列表

5
6
7
8
15
16
17
25
26
27

我想要的是差距列表

1-4
9-14
18-24

我不知道perlSQL或任何花哨的东西,但我认为我可能能够做一些从下一个数字中减去一个数字的事情。然后,我至少可以grep输出差异不是1-1的输出,并使用它来获得差距。

4

6 回答 6

78

使用

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分配给当前的第一列
于 2013-04-07T20:58:34.883 回答
4

有趣的问题。

sputnick 的 awk one-liner 很不错。我写不出比他更简单的了。我只是使用 diff 添加另一种方式:

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

您的示例的输出将是:

1,4
9,14
18,24

我知道里面有逗号,而不是-. 您可以用 sed 替换 grep 来获取-, grep 无法更改输入文本......但想法是一样的。

希望能帮助到你。

于 2013-04-07T22:17:56.600 回答
3

红宝石答案

也许其他人可以为您提供您要求的 Bash 或 Awk 解决方案。但是,我认为任何基于 shell 的答案都可能针对您的数据集非常本地化,并且不是很可扩展。用 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

于 2013-04-07T22:27:44.837 回答
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单个数字间隙之类的行。

于 2013-04-07T20:51:27.437 回答
0

Perl 解决方案类似于 StardustOne 的 awk 解决方案:

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 代码

于 2015-09-15T18:20:29.403 回答
0

给定输入file ,在file旁边使用numintervalutil及其输出,然后使用 、和munge它:pastetrxargssedprintf

gaps() { paste  <(echo; numinterval "$1" | tr 1 '-' | tr -d '[02-9]') "$1" | 
         tr -d '[:blank:]' | xargs echo | 
         sed 's/ -/-/g;s/-[^ ]*-/-/g' | xargs printf "%s\n" ; }

输出gaps file

5-8
15-17
25-27

这个怎么运作。的输出paste <(echo; numinterval file) file看起来像:

    5
1   6
1   7
1   8
7   15
1   16
1   17
8   25
1   26
1   27

从那里我们主要替换第 1 列中的内容,并调整间距。s被1s 替换,-较高的数字被空白。用 删除一些空格tr。用单个连字符“ 5-8 ”替换诸如“ 5-6-7-8 ”之类的连字符,这就是输出。

于 2018-04-10T19:17:19.517 回答