从 .csv 文件创建用户 2

从 .csv 文件创建用户 2

我是一名学生,在创建自己的脚本方面付出了巨大的努力。一般来说,我可以做一个爆炸性的工作 script-kiddie-ing,并按照提供的信息和规则添加到其他人所做的事情(是的,我知道我感到羞耻),但在尝试使用 bash/python 几年之后显然,我确实没有所需的脑力,无法从头开始创造来拯救我的生命,所以我在这里。四年前有一个关于类似主题的帖子,对于我想要实现的目标来说,它似乎是沿着正确的道路,然而,对于我的一生,我似乎无法弄清楚我在哪里出错了。下面是我想感谢 jesse_b 的脚本,因为我一直在修改我需要使用的参数,但不幸的是,当我运行脚本时,我不断地得到我认为是某些东西的手册页我认为是在脚本中(可能是 useradd?)。如果有人能够保护我并提供建设性的反馈,我将不胜感激。

#! /usr/bin/bash

MY_INPUT='Newbies.csv'
declare -a A_SURNAME
declare -a A_FIRST
declare -a A_USERNAME
declare -a A_GROUP
declare -a A_SECGROUP
declare -a A_COMMENTS
while IFS=, read -r COL1 COL2 COL3 COL4 COL5 COL6 TRASH; do
    A_SURNAME+=("$COL1")
    A_FIRST+=("$COL2")
    A_USERNAME+=("$COL3")
    A_GROUP+=("$COL4")
    A_SECGROUP+=("$COL5")
    A_COMMENTS+=("$COL6")
done <"$MY_INPUT"

for index in "${!A_USERNAME[@]}"; do
    useradd -g "${A_GROUP[$index]}" -G "${A_SECGROUP[$index]}" -c "${A_COMMENTS[$index]}"

done

参数示例在此输入图像描述:姓氏、名字、用户名、组、secgroup、评论:

Esche,Adlai,aesche,Accounting,Emp,5326,
West,Kaila,kwest,Accounting,Emp,0699,
July,Markos,mjuly,MArketing,Emp,7208,

参考帖子的链接:从 .csv 文件创建用户

答案1

除了忘记将用户名添加到 useradd 行的末尾之外,您还使事情变得比需要的更加复杂。

您不需要多个数组变量(除非您打算对 CSV 数据执行更多操作帐户已创建 - 即使这样,您最好在现有for循环内执行此操作)。您还使用了bash(这是一种在文本处理方面很糟糕的语言)而不是实际上擅长文本处理的语言(例如awkperl)。

以下是如何在perl一行中完成您想要的事情:

$ perl -lne '($surname,$first,$username,$group,$secgroup,$comments) = split /\s*,\s*/;
    system("echo","useradd","-g",$group,"-G",$secgroup,"-c",$comments,$username)' Newbies.csv

输出示例:

useradd -g Accounting -G Emp -c 5326 aesche
useradd -g Accounting -G Emp -c 0699 kwest
useradd -g MArketing -G Emp -c 7208 mjuly

这被写成一个空运行,只打印它的内容执行此操作,而无需实际添加任何用户帐户。验证它正确生成命令后,"echo"从命令中删除。system()useradd

请注意,与 bash 不同,使用 perl 函数时不需要引用变量system() - 给定列表的每个元素都作为单独的、单独的参数传递给系统正在执行的程序(在本例中,程序是echo,或者从列表中useradd删除后"echo"),即使它包含空格字符。除非您传递通配符或其他 shell 元字符,否则system()不会使用 shell,也不会受到 shell 的分词或扩展的影响。避免传递通配符很容易,因为 perl 有自己的内置方法来扩展 glob 或构造一个充满文件名的数组。

唯一一次可能需要引用变量的情况是将它们组合成一个字符串。例如,您可以使用以下命令将名字和姓氏添加到 GECOS 字段:

$ perl -lne '($surname,$first,$username,$group,$secgroup,$comments) = split /\s*,\s*/;
    system("echo","useradd","-g",$group,"-G",$secgroup,"-c","$first $surname - $comments",$username)' Newbies.csv 

即便如此,还有许多其他方法可以做到这一点 - 例如使用.串联运算符:

$first . " " . $surname . " - " . $comments

或使用join()

join(" ",$first,$surname,"-",$comments)

输出示例:

useradd -g Accounting -G Emp -c Adlai Esche - 5326 aesche
useradd -g Accounting -G Emp -c Kaila West - 0699 kwest
useradd -g MArketing -G Emp -c Markos July - 7208 mjuly

从此处显示的输出来看并不明显,但注释实际上是作为单身的useradd的选项的参数-c。例如Adlai Esche - 5326是选项的单个参数-c不是四个单独的参数,一个恰好包含空格字符的字符串。

"echo",如果您将 替换为"printf","%s\n",,以便将每个参数打印在单独的行上,您可以看到这一点 -例如

$ perl -lne '($surname,$first,$username,$group,$secgroup,$comments) = split /\s*,\s*/;
    system("printf","%s\n","useradd","-g",$group,"-G",$secgroup,"-c","$first $surname - $comments",$username)' Newbies.csv
useradd
-g
Accounting
-G
Emp
-c
Adlai Esche 5326
aesche
...

版本awk会非常相似。主要区别在于,它awk根据字段分隔符(FS变量,默认为空格,但您可以设置为逗号-F,)自动将其输入拆分为列($1,$2,$3....),而 awk 的系统函数只需要一个字符串参数,因此您必须自己进行引用,类似于 sh 或 bash 的要求。

perl 有类似的-F选项,也可以自动将其输入拆分为列(拆分为名为 的数组),但使用有意义的变量名称(例如,而不是 )@F更容易阅读代码。$group$F[2]


bash版本:

#!/bin/bash

MY_INPUT='Newbies.csv'

while IFS=, read -r surname first username group secgroup comments; do 
    echo useradd -g "$group" -G "$secgroup" -c "$comments" "$username"
    #echo useradd -g "$group" -G "$secgroup" -c "$first $surname - $comments" "$username"
    #printf "%s\n" useradd -g "$group" -G "$secgroup" -c "$first $surname - $comments" "$username"
done < "$MY_INPUT"

再次强调,这是作为一次演练编写的。删除echo以允许它实际创建用户帐户。它还包含一条注释,显示如何将名字和姓氏添加到 GECOS 字段。

输出与 perl 版本中的相同:

useradd -g Accounting -G Emp -c Adlai Esche - 5326 aesche
useradd -g Accounting -G Emp -c Kaila West - 0699 kwest
useradd -g MArketing -G Emp -c Markos July - 7208 mjuly

或者:

useradd -g Accounting -G Emp -c Adlai Esche - 5326 aesche
useradd -g Accounting -G Emp -c Kaila West - 0699 kwest
useradd -g MArketing -G Emp -c Markos July - 7208 mjuly

结合 bash 和 perl:

#!/bin/bash

MY_INPUT='Newbies.csv'

perl -lne '($surname,$first,$username,$group,$secgroup,$comments) = split /\s*,\s*/;
    system("echo","useradd","-g",$group,"-G",$secgroup,"-c",$comments,$username)' "$MY_INPUT"

这是一个如此简单的任务,以至于它并没有真正提供一个很好的例子来说明为什么最好使用 awk 或 perl 或几乎任何东西(除了 bash)来进行文本处理。看为什么使用 shell 循环处理文本被认为是不好的做法?

然而,即使在这里,perl 版本也更快(并不重要,除非您有数千个帐户要创建)split /\s*,\s*/从逗号分隔的字段中删除所有前导和尾随空白 - 在 Perl 中微不足道,在 bash 中需要做更多的工作。即它“清理”输入数据,以便它能够正确地满足我们想要使用它的目的 - unix 中的用户名和组名可能不以空格开头。

相关内容