bash 中的动态连续编号
Dynamic continuous numbering in bash
我有一个文本文件作为脚本的数据库。该文件在示例中有一列 "ID"。
数据库的格式为
UID:Item Name:Quantity:Price:Date 添加
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
还不是很擅长。因此,如果您有一个使用 awk
的解决方案,请也指导我完成它。非常感谢!
如果我对问题的理解正确,您正在查找从顶部开始的第一个 "free" 数字。类似于:
$ awk -F: '{s=sprintf("%04d",NR)} s!={print s; exit}' FirstDB.txt
可以为所欲为。我在这里假设,没有 2 个客户端可以同时 add/delete。
这甚至可以缩短为:
$ awk -F: '(s=sprintf("%04d",NR))!={print s; exit}' FirstDB.txt
awk
救援!
假设编辑后序列将不再排序
awk -F: '{a[+0]} END{for(i=1;i<=NR;i++) if(!(i in a)) print i}'
将 return 您从第一列(假设数字字段)中第一个缺失的数字。
测试
create a shuffled list of formatted sequence numbers with "0003" missing.
awk 'BEGIN{for(i=1;i<=10;i++) printf "%04d\n",i}' | shuf | awk '!=3'
0009
0001
0006
0004
0002
0005
0008
0010
0007
pipe to the script
... | awk -F: '{a[+0]} END{for(i=1;i<=NR;i++) if(!(i in a)) print i}'
returns as expected
3
但是,如果您的列表没有空白,这不会 return 任何东西。要处理这种情况,您需要 return 最大数字 + 1。通过此修改,测试用例和脚本变为
$ awk 'BEGIN{for(i=1;i<=10;i++) printf "%04d\n",i}' |
shuf |
awk -F: '{a[+0]} >max{max=}
END {for(i=1;i<=NR;i++) if(!(i in a)) {print i; exit}
print max+1}'
11
注意如果您在每次插入记录后对文件进行排序,则可以避免很多复杂性。
我有一个文本文件作为脚本的数据库。该文件在示例中有一列 "ID"。
数据库的格式为 UID:Item Name:Quantity:Price:Date 添加
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
还不是很擅长。因此,如果您有一个使用 awk
的解决方案,请也指导我完成它。非常感谢!
如果我对问题的理解正确,您正在查找从顶部开始的第一个 "free" 数字。类似于:
$ awk -F: '{s=sprintf("%04d",NR)} s!={print s; exit}' FirstDB.txt
可以为所欲为。我在这里假设,没有 2 个客户端可以同时 add/delete。
这甚至可以缩短为:
$ awk -F: '(s=sprintf("%04d",NR))!={print s; exit}' FirstDB.txt
awk
救援!
假设编辑后序列将不再排序
awk -F: '{a[+0]} END{for(i=1;i<=NR;i++) if(!(i in a)) print i}'
将 return 您从第一列(假设数字字段)中第一个缺失的数字。
测试
create a shuffled list of formatted sequence numbers with "0003" missing.
awk 'BEGIN{for(i=1;i<=10;i++) printf "%04d\n",i}' | shuf | awk '!=3'
0009
0001
0006
0004
0002
0005
0008
0010
0007
pipe to the script
... | awk -F: '{a[+0]} END{for(i=1;i<=NR;i++) if(!(i in a)) print i}'
returns as expected
3
但是,如果您的列表没有空白,这不会 return 任何东西。要处理这种情况,您需要 return 最大数字 + 1。通过此修改,测试用例和脚本变为
$ awk 'BEGIN{for(i=1;i<=10;i++) printf "%04d\n",i}' |
shuf |
awk -F: '{a[+0]} >max{max=}
END {for(i=1;i<=NR;i++) if(!(i in a)) {print i; exit}
print max+1}'
11
注意如果您在每次插入记录后对文件进行排序,则可以避免很多复杂性。