bash中的动态连续编号

时间:2017-09-12 15:39:55

标签: arrays bash awk sed text-manipulation

我有一个文本文件,充当我脚本的数据库。该文件有一个" ID"的列。在例子中。

数据库的格式为 UID:商品名称:数量:价格:添加日期

cat FirstDB.txt

输出:

0001:Fried Tarantula:45:100:2017-08-03
0002:Wasp Crackers:18:25:2017-08-04
0003:Century Egg:19:50:2017-08-05
0004:Haggis Flesh:20:90:2017-08-06
0005:Balut (Egg):85:15:2017-08-07
0006:Bear Claw:31:550:2017-08-08
0007:Durian Fruit:70:120:2017-08-09
0008:Live Cobra heart:20:375:2017-08-10
0009:Monkey Brains:30:200:2017-08-11
0010:Casu Marzu:25:1030:2017-08-12

现在,我创建的功能允许某个用户使用相同的格式在文本文件中添加新条目(我已经创建了这个)。但是,这里真正的技巧是用户还可以选择删除某个项目。在示例中,用户想要从文本文件中删除Century Egg,输出将是:

0001:Fried Tarantula:45:100:2017-08-03
0002:Wasp Crackers:18:25:2017-08-04
0004:Haggis Flesh:20:90:2017-08-06
0005:Balut (Egg):85:15:2017-08-07
0006:Bear Claw:31:550:2017-08-08
0007:Durian Fruit:70:120:2017-08-09
0008:Live Cobra heart:20:375:2017-08-10
0009:Monkey Brains:30:200:2017-08-11
0010:Casu Marzu:25:1030:2017-08-12

然后,如果用户希望在数据库中添加任何项目,我希望用户使用UID 0003,因为它已经免费。我该如何实现这一目标?到目前为止我一直坚持下去。我相信awk在这里很有用,但我并没有保持我的选项关闭,而且我对脚本很新,而且我对awk并不是那么好。因此,如果您有一个使用awk的解决方案,请引导我完成它。非常感谢你!

2 个答案:

答案 0 :(得分:1)

awk救援!

假设编辑后不再订购序列

awk -F: '{a[$1+0]} END{for(i=1;i<=NR;i++) if(!(i in a)) print i}'

将返回第一列中的第一个缺失数字(假设数字字段)。

测试

  

创建一个混乱的格式化序列号列表,缺少“0003”。

awk 'BEGIN{for(i=1;i<=10;i++) printf "%04d\n",i}' | shuf | awk '$1!=3' 

0009
0001
0006
0004
0002
0005
0008
0010
0007
  

管道到脚本

... | awk -F: '{a[$1+0]} END{for(i=1;i<=NR;i++) if(!(i in a)) print i}'
  

按预期返回

3

但是,如果您的列表没有间隙,则不会返回任何内容。要处理这种情况,您需要返回最大数字+ 1.通过此修改,测试用例和脚本将变为

$ awk 'BEGIN{for(i=1;i<=10;i++) printf "%04d\n",i}' | 
  shuf | 
  awk -F: '{a[$1+0]} $1>max{max=$1} 
       END {for(i=1;i<=NR;i++) if(!(i in a)) {print i; exit} 
            print max+1}'

11

注意如果您在每次插入记录后对文件进行排序,则可以避免大部分复杂性。

答案 1 :(得分:0)

如果我正确理解了这个问题,你就是从顶部开始寻找第一个“免费”号码。类似的东西:

$ awk -F: '{s=sprintf("%04d",NR)} s!=$1{print s; exit}' FirstDB.txt

可以做你想做的事。我在这里假设,没有2个客户端可以同时添加/删除。

这甚至可以缩短为:

$ awk -F: '(s=sprintf("%04d",NR))!=$1{print s; exit}' FirstDB.txt