【问题标题】:Bash Script Help Needed需要 Bash 脚本帮助
【发布时间】:2011-12-15 18:58:58
【问题描述】:

所以我正在处理一项任务,并且非常接近完成它。只是最后一部分有问题。这是我猜想的全部问题,只是为了让你知道我想要做什么 -

编写一个名为 make_uid 的 shell 脚本,它在给定包含用户全名的文件的情况下创建用户登录名。您的脚本需要读取 newusers 文件,并为文件中的每个名称创建一个登录名,该登录名由用户名的第一个字符和最多 7 个字符的姓氏组成。如果姓氏少于七个字符,请使用整个姓氏。如果用户只有一个名称,则使用提供的任何名称(在 newusers 文件中)生成一个 8 字符长的登录名。注意:登录名必须全部小写!

创建登录名后,您需要检查 passwd 文件以确保您刚刚创建的登录名不存在。如果名称存在,请去掉您创建的名称的最后一个字符,并添加一个数字(从 1 开始)并再次检查 passwd 文件。重复此过程,直到您创建唯一的用户登录名。获得唯一用户名后,将其附加到 passwd 文件,然后继续处理 newusers 文件。

到目前为止,这是我的代码。此时,它会生成一个包含所有登录名的完整 passwd 文件。我只是在对列表进行排序和相应地编辑重复项的最后一步时遇到了麻烦。

#!/bin/bash
#Let's make some login names!

declare -a first
declare -a last
declare -a password
file=newusers

first=( $(cat $file | cut -b1 | tr "[:upper:]" "[:lower:]" | tr '\n' ' ') )
for (( i=0; i<${#first[@]}; i++)); do
  echo ${first[i]} >> temp1
done

last=( $(cat $file | awk '{print $NF}' $file | cut -b1-7 | tr "[:upper:]" "[:lower:]"))
for (( i=0; i<${#last[@]}; i++)); do
  echo ${last[i]} >> temp2
done

paste -d "" temp1 temp2 >> passwd
sort -o passwd passwd
more passwd
rm temp1 temp2

【问题讨论】:

  • 旁白:尽量不要不必要地使用cat,就像这里一样。您可以轻松地将$file 传递给cutawk,而无需添加其他程序... :-)
  • 是的,并且......在最后的处理中,你 cat $file 然后 awk .. $file,所以你得到的数据是 2 倍。此外,对于“编辑重复项”的问题,请尝试 sort -u -o ... '-u' 以获得唯一或 sort ...|uniq ... 是长手版本。祝你好运。

标签: bash unix


【解决方案1】:

好吧,我可能不应该回答家庭作业,但也许它会帮助你学习。

#!/bin/bash

infile=./newusers
outfile=./passwd

echo -n "" > $outfile

cat $infile | while read line; do
    read firstName lastName < <(echo $line)

    if [ -z "$lastName" ]; then
            login=${firstName:0:8}
    else
            login=${firstName:0:1}${lastName:0:7}
    fi

    digit=1
    while fgrep -q $login $outfile; do
            login=${login%?}$digit
            let digit++
    done

    echo $login >> $outfile
done

可能有一些方法可以在单个命令中而不是循环中进行 fgrep 检查,但这是最易读的。此外,如果名称少于 8 个字符,您的问题陈述没有说明该怎么做,因此此解决方案无法解决此问题,并且如果名称很短,则会生成较短的密码。

编辑:fgrep 循环假定重复项少于 10 个。如果没有,你需要让它更健壮一点:

    lastDigit="?"
    nextDigit=1
    while fgrep -q $login $outfile; do
            login=${login%$lastDigit}$nextDigit
            let lastDigit=nextDigit
            let nextDigit++
    done

【讨论】:

  • 这不适用于我对 cat 的使用。 “while”语句不是一个可以将文件名作为参数传递给它的命令。
  • 即使这样可行,它也会使代码更难阅读。我认为可读性比避免使用 cat 更重要。
【解决方案2】:

在添加数字之前将所有用户名添加到另一个文件中。使用fgrep -xc theusername thisotherfile,这将返回一个数字。如果不为 0,则将数字附加到登录名。

【讨论】: