增加和修改列表中的数字
Incrementing and modifying numbers on list
我正在尝试编写一个脚本作为注册表的一部分。一切都已准备就绪,但是,我想实现一个类似于 UID 在 bash 中的工作方式的 "UID" 函数。然而,这是棘手的部分:每次添加用户时,我要实施的 UID 都会增加 1,如果该用户删除他/她的帐户,他的帐户将从数据库中删除,从而删除用于他的 UID。我想要用来检查现有 UID 的脚本,如果有差异,它会填充它。
示例
Name:UID
Apple:0001
Bag:0002
Cat:0003
Dog:0004
Cat 删除了他的帐户,因此新列表将是
Apple:0001
Bag:0002
Dog:0004
如果新用户创建了一个帐户,它应该是
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
一切都已修复,包括从数据库中删除帐户我只是在实现 UID 的增量及其填充缺失数字的能力方面遇到了问题。非常感谢您的帮助!非常感谢!
编辑:我大致知道在将它们放入循环结构时要使用什么,例如 sed 和 cmp,但还不足以将它们变成我想要的东西。
维护一个空闲索引列表(一个数组),如果有空闲索引,则使用它来查找空闲索引:
declare -a free_indexes=()
...
if [[ action == "remove" ]]; then
free_indexes=( ${free_indexes[@]} $removed_index )
elif [[ action == "add" ]]; then
if [[ ${#free_indexes[@]} -ne 0 ]]; then
index=${free_indexes[0]}
unset free_indexes[0]
free_indexes=( ${free_indexes[@]} )
else
index=next_index
fi
fi
awk 解决办法:
假设关键文件名为 users
,在 Cat 删除他的帐户后具有以下内容:
Name:UID
Apple:0001
Bag:0002
Dog:0004
awk -v nuser="NEWUSER" -F':' 'NR>1 && uid && (int()-uid>1){
[=11=]=sprintf("%s:%04d\n%s",nuser,uid+1,[=11=]) }
{ uid=int() }1' users > tmp$$ && mv tmp$$ users
users
处理后的文件:
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
假设 uids.txt 存在
cat uids.txt
Apple:0001
Bag:0002
Dog:0004
您可以使用 bash-fun 库以功能方式完成您的工作:)
source <(curl -Ls https://raw.githubusercontent.com/ssledz/bash-fun/master/src/fun.sh)
next_id() {
prepend $(tup 0 0) | cut -d':' -f2 \
| map lambda a . 'echo $((a))' | sort \
| scanl lambda acc el . 'cnt=$(tupl $acc); cnt=$((cnt+1)); tup $cnt $el' \
| filter lambda a . 'cnt=$(tupl $a); el=$(tupr $a); [[ $cnt -ne $a ]] && ret true || ret false' \
| tupl | fold -w 1 | append 0 0 0 0 | take 4 | revers | join ''
}
echo NEWUSER:$(cat uids.txt | next_id) | cat - uids.txt |sort -t ':' -n -k2
你应该在return得到
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
在这里你可以找到我关于这个库的介绍:fun.sh
无论输入文件的顺序如何、有多少间隙或这些间隙有多大,这都有效:
$ cat addUser.awk
BEGIN { FS=OFS=":"; min=max=1 }
NR==1 { print; next }
{
uid = +0
uid2user[uid] =
min = (min > uid ? uid : min)
max = (max < uid ? uid : max)
}
END {
fmt = "%s" OFS "%04d\n"
for (uid=min; uid<=max; uid++) {
if (uid in uid2user) {
printf fmt, uid2user[uid], uid
}
else if (newUser != "") {
printf fmt, newUser, uid
newUser = ""
}
}
if (newUser != "") {
printf fmt, newUser, uid
}
}
.
$ cat users1
Name:UID
Cat:0003
Apple:0001
Dog:0004
Bag:0002
$ awk -v newUser="NEWUSER" -f addUser.awk users1
Name:UID
Apple:0001
Bag:0002
Cat:0003
Dog:0004
NEWUSER:0005
$ cat users2
Name:UID
Bag:0002
Dog:0004
Apple:0001
$ awk -v newUser="NEWUSER" -f addUser.awk users2
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
$ cat users3
Name:UID
$ awk -v newUser="NEWUSER" -f addUser.awk users3
Name:UID
NEWUSER:0001
.
$ cat users4
Name:UID
Bag:0002
Dog:0004
Apple:0001
Frog:0006
$ awk -v newUser="NEWUSER" -f addUser.awk users4
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
Frog:0006
$ cat users5
Name:UID
Bag:0002
Apple:0001
Frog:0006
$ awk -v newUser="NEWUSER" -f addUser.awk users5
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Frog:0006
考虑到您的 Input_file 与显示的示例相同,因此我在这里考虑了您的陈述 2 种情况。
假设我们有以下 Input_file:
cat Input_file
Name:UID
Apple:0001
Bag:0002
Dog:0004
Billi:0016
ascs:0018
ewdwdwd:0022
qce:0023
ooidw:24
fewfewf:30
1st: 当只有 1 个名为 NEW_USER 的用户时,您必须在所有地方输入,那么以下内容可能会对您有所帮助。
awk -v new="NEW_USER" -F":" '
NR==+1;
NR!=+1{
q=NR-1;
while(q<){
q=sprintf("%04d",q);
print new":"q;
q++
};
NR=q+1;
print
}' Input_file
输出如下。
Name:UID
Apple:0001
Bag:0002
NEW_USER:0003
Dog:0004
NEW_USER:0005
NEW_USER:0006
NEW_USER:0007
NEW_USER:0008
NEW_USER:0009
NEW_USER:0010
NEW_USER:0011
NEW_USER:0012
NEW_USER:0013
NEW_USER:0014
NEW_USER:0015
Billi:0016
NEW_USER:0017
ascs:0018
NEW_USER:0019
NEW_USER:0020
NEW_USER:0021
ewdwdwd:0022
qce:0023
ooidw:24
NEW_USER:0025
NEW_USER:0026
NEW_USER:0027
NEW_USER:0028
NEW_USER:0029
fewfewf:30
2nd: 如果你有像 new_user1、new_user2 等这样的用户数量(我从你的陈述中预测您提到了很多缺失的用户,以防您在 sheet).
中有多个用户需要更新
awk -v new="NEW_USER,NEW_USER1,NEW_USER2,NEW_USER3" -F":" 'BEGIN{
len=split(new, a,",")
}
NR==+1;
NR!=+1{
q=NR-1;
while(q<){
q=sprintf("%04d",q);
if(i==len){
i=""
};
print a[++i]":"q;
q++
};
NR=q+1;
i="";
print
}' Input_file
输出如下。
Name:UID
Apple:0001
Bag:0002
NEW_USER:0003
Dog:0004
NEW_USER:0005
NEW_USER1:0006
NEW_USER2:0007
NEW_USER3:0008
NEW_USER:0009
NEW_USER1:0010
NEW_USER2:0011
NEW_USER3:0012
NEW_USER:0013
NEW_USER1:0014
NEW_USER2:0015
Billi:0016
NEW_USER:0017
ascs:0018
NEW_USER:0019
NEW_USER1:0020
NEW_USER2:0021
ewdwdwd:0022
qce:0023
ooidw:24
NEW_USER:0025
NEW_USER1:0026
NEW_USER2:0027
NEW_USER3:0028
NEW_USER:0029
fewfewf:30
我正在尝试编写一个脚本作为注册表的一部分。一切都已准备就绪,但是,我想实现一个类似于 UID 在 bash 中的工作方式的 "UID" 函数。然而,这是棘手的部分:每次添加用户时,我要实施的 UID 都会增加 1,如果该用户删除他/她的帐户,他的帐户将从数据库中删除,从而删除用于他的 UID。我想要用来检查现有 UID 的脚本,如果有差异,它会填充它。
示例
Name:UID
Apple:0001
Bag:0002
Cat:0003
Dog:0004
Cat 删除了他的帐户,因此新列表将是
Apple:0001
Bag:0002
Dog:0004
如果新用户创建了一个帐户,它应该是
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
一切都已修复,包括从数据库中删除帐户我只是在实现 UID 的增量及其填充缺失数字的能力方面遇到了问题。非常感谢您的帮助!非常感谢!
编辑:我大致知道在将它们放入循环结构时要使用什么,例如 sed 和 cmp,但还不足以将它们变成我想要的东西。
维护一个空闲索引列表(一个数组),如果有空闲索引,则使用它来查找空闲索引:
declare -a free_indexes=()
...
if [[ action == "remove" ]]; then
free_indexes=( ${free_indexes[@]} $removed_index )
elif [[ action == "add" ]]; then
if [[ ${#free_indexes[@]} -ne 0 ]]; then
index=${free_indexes[0]}
unset free_indexes[0]
free_indexes=( ${free_indexes[@]} )
else
index=next_index
fi
fi
awk 解决办法:
假设关键文件名为 users
,在 Cat 删除他的帐户后具有以下内容:
Name:UID
Apple:0001
Bag:0002
Dog:0004
awk -v nuser="NEWUSER" -F':' 'NR>1 && uid && (int()-uid>1){
[=11=]=sprintf("%s:%04d\n%s",nuser,uid+1,[=11=]) }
{ uid=int() }1' users > tmp$$ && mv tmp$$ users
users
处理后的文件:
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
假设 uids.txt 存在
cat uids.txt
Apple:0001
Bag:0002
Dog:0004
您可以使用 bash-fun 库以功能方式完成您的工作:)
source <(curl -Ls https://raw.githubusercontent.com/ssledz/bash-fun/master/src/fun.sh)
next_id() {
prepend $(tup 0 0) | cut -d':' -f2 \
| map lambda a . 'echo $((a))' | sort \
| scanl lambda acc el . 'cnt=$(tupl $acc); cnt=$((cnt+1)); tup $cnt $el' \
| filter lambda a . 'cnt=$(tupl $a); el=$(tupr $a); [[ $cnt -ne $a ]] && ret true || ret false' \
| tupl | fold -w 1 | append 0 0 0 0 | take 4 | revers | join ''
}
echo NEWUSER:$(cat uids.txt | next_id) | cat - uids.txt |sort -t ':' -n -k2
你应该在return得到
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
在这里你可以找到我关于这个库的介绍:fun.sh
无论输入文件的顺序如何、有多少间隙或这些间隙有多大,这都有效:
$ cat addUser.awk
BEGIN { FS=OFS=":"; min=max=1 }
NR==1 { print; next }
{
uid = +0
uid2user[uid] =
min = (min > uid ? uid : min)
max = (max < uid ? uid : max)
}
END {
fmt = "%s" OFS "%04d\n"
for (uid=min; uid<=max; uid++) {
if (uid in uid2user) {
printf fmt, uid2user[uid], uid
}
else if (newUser != "") {
printf fmt, newUser, uid
newUser = ""
}
}
if (newUser != "") {
printf fmt, newUser, uid
}
}
.
$ cat users1
Name:UID
Cat:0003
Apple:0001
Dog:0004
Bag:0002
$ awk -v newUser="NEWUSER" -f addUser.awk users1
Name:UID
Apple:0001
Bag:0002
Cat:0003
Dog:0004
NEWUSER:0005
$ cat users2
Name:UID
Bag:0002
Dog:0004
Apple:0001
$ awk -v newUser="NEWUSER" -f addUser.awk users2
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
$ cat users3
Name:UID
$ awk -v newUser="NEWUSER" -f addUser.awk users3
Name:UID
NEWUSER:0001
.
$ cat users4
Name:UID
Bag:0002
Dog:0004
Apple:0001
Frog:0006
$ awk -v newUser="NEWUSER" -f addUser.awk users4
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Dog:0004
Frog:0006
$ cat users5
Name:UID
Bag:0002
Apple:0001
Frog:0006
$ awk -v newUser="NEWUSER" -f addUser.awk users5
Name:UID
Apple:0001
Bag:0002
NEWUSER:0003
Frog:0006
考虑到您的 Input_file 与显示的示例相同,因此我在这里考虑了您的陈述 2 种情况。 假设我们有以下 Input_file:
cat Input_file
Name:UID
Apple:0001
Bag:0002
Dog:0004
Billi:0016
ascs:0018
ewdwdwd:0022
qce:0023
ooidw:24
fewfewf:30
1st: 当只有 1 个名为 NEW_USER 的用户时,您必须在所有地方输入,那么以下内容可能会对您有所帮助。
awk -v new="NEW_USER" -F":" '
NR==+1;
NR!=+1{
q=NR-1;
while(q<){
q=sprintf("%04d",q);
print new":"q;
q++
};
NR=q+1;
print
}' Input_file
输出如下。
Name:UID
Apple:0001
Bag:0002
NEW_USER:0003
Dog:0004
NEW_USER:0005
NEW_USER:0006
NEW_USER:0007
NEW_USER:0008
NEW_USER:0009
NEW_USER:0010
NEW_USER:0011
NEW_USER:0012
NEW_USER:0013
NEW_USER:0014
NEW_USER:0015
Billi:0016
NEW_USER:0017
ascs:0018
NEW_USER:0019
NEW_USER:0020
NEW_USER:0021
ewdwdwd:0022
qce:0023
ooidw:24
NEW_USER:0025
NEW_USER:0026
NEW_USER:0027
NEW_USER:0028
NEW_USER:0029
fewfewf:30
2nd: 如果你有像 new_user1、new_user2 等这样的用户数量(我从你的陈述中预测您提到了很多缺失的用户,以防您在 sheet).
中有多个用户需要更新awk -v new="NEW_USER,NEW_USER1,NEW_USER2,NEW_USER3" -F":" 'BEGIN{
len=split(new, a,",")
}
NR==+1;
NR!=+1{
q=NR-1;
while(q<){
q=sprintf("%04d",q);
if(i==len){
i=""
};
print a[++i]":"q;
q++
};
NR=q+1;
i="";
print
}' Input_file
输出如下。
Name:UID
Apple:0001
Bag:0002
NEW_USER:0003
Dog:0004
NEW_USER:0005
NEW_USER1:0006
NEW_USER2:0007
NEW_USER3:0008
NEW_USER:0009
NEW_USER1:0010
NEW_USER2:0011
NEW_USER3:0012
NEW_USER:0013
NEW_USER1:0014
NEW_USER2:0015
Billi:0016
NEW_USER:0017
ascs:0018
NEW_USER:0019
NEW_USER1:0020
NEW_USER2:0021
ewdwdwd:0022
qce:0023
ooidw:24
NEW_USER:0025
NEW_USER1:0026
NEW_USER2:0027
NEW_USER3:0028
NEW_USER:0029
fewfewf:30