Поэтому я застрял при попытке создать скрипт bash в то время как функция цикла, которая принимает входные данные из /etc /passwd и выводит, сколько пользователей использует bash, nolongin, csh и ksh. Я считаю, что я должен использовать кошку и вырезать. И я знаю, что тип оболочки, которую использует пользователь, находится в седьмом поле.

Правильно ли я считаю, что я должен создать переменную для каждого типа оболочки и увеличивать ее каждый раз, когда находит пользователя, который использует эту конкретную оболочку?

Пока это код, который у меня есть, но по какой-то причине он выводит только последний оператор if ..

declare -i bash;
declare -i nologin;
declare -i csh;
declare -i ksh;

bash=0;
nologin=0;
csh=0;
ksh=0;
cat /etc/passwd | cut -d: -f7 $line | while read line;
do
    if [ $line == "bash" ]
            then
                    bash=bash+1;
    else  fi [ $line == "/sbin/nologin" ]
            then
                    nologin=nologin+1;
    else fi [ $line == "chs" ]
            then
                    chs=chs+1;
    else
            then
                    ksh=ksh+1;
    fi
done

Обновление: пока я изменил код и обновил то, что у меня есть. Он перебирает и выдает правильную часть оператора if, но у меня возникают проблемы при попытке увеличить мои переменные.

4 ответа4

3

Я не уверен, что это домашнее задание, поэтому оно может не соответствовать вашим требованиям, но на самом деле вам не нужен целый сценарий для этого. Это можно сделать с помощью одной строки.

cat /etc/passwd | cut -d ':' -f 7 | sort | uniq -c

Вот как выглядит результат

  4 /bin/bash
  6 /sbin/nologin
  4 /usr/bin/csh
 13 /usr/bin/ksh

Это работает так, что uniq(1) «Фильтрует соседние совпадающие строки из INPUT», и поэтому с опцией -c он будет считать соседние строки, поэтому нам нужно сначала отсортировать строки, чтобы все совпадающие строки были смежными.

1

Вот моя версия:

#!/bin/bash

bash=0;
nologin=0;
csh=0;
ksh=0;

while read line;
do
    innerline=$(echo "$line"| cut -d: -f7)

    if [[ $innerline == "/bin/bash" ]]
    then
                    bash=$(echo "$bash+1"|bc);
    elif [[ $innerline == "/sbin/nologin" ]]
    then
                    nologin=&(echo "$nologin+1"|bc);
    elif [[ $innerline == "/bin/csh" ]]
    then
                    csh=$(echo "$csh+1"|bc);
    else
                    ksh=$(echo "$ksh+1"|bc);
    fi
done < /etc/passwd

echo "$bash $nologin $csh $ksh"

Чтобы увеличить значения, я передаю задание на вычисление в bc который является небольшой утилитой калькулятора.

Дайте мне знать, если это работает для вас.

Если честно, должен сказать, что мне действительно не нравится это решение. Цикл while не нужен, и я предпочитаю решение @Nat, так как вы четко заявили, что цикл while должен присутствовать - вот оно.

PS. Это просто ужасная идея

else
                        ksh=$(echo "$ksh+1"|bc);

предположить, что каждая неизвестная / непревзойденная оболочка - это ksh .

0

Некоторые думали

 cat /etc/passwd | while read line;

поместит в линию

 tmpfoo:x:1004:1005:utilisateur test sudo:/home/tmpfoo:/bin/bash

затем,

  cut -d: -f7 $line == "bash"

будет оценивать

 cut -d: -f7 tmpfoo:x:1004:1005:utilisateur test sudo:/home/tmpfoo:/bin/bash == "bash"

Cut будет искать в 3 файлах tmpfoo:x:1004:1005:utilisateur, test и sudo:/home/tmpfoo:/bin/bash, что, вероятно, не то, что вам нужно.

в качестве подарка попробуйте этот пример цикла

cat /etc/passwd |  cut -d: -f7 | while read line;
do
    echo $line
done
0

Я считаю, что я должен использовать cat и cut .

Это то, над чем я работаю для класса Unix, поэтому я должен создать функцию цикла while.

Конечно, файлы, в которых записи имеют переменную длину, разделенную символами новой строки, а поля переменной длины, разделенные одним символом-разделителем, например файл паролей UNIX версии 7, - это то, что awk превосходит. Так что для тех людей, которые приезжают сюда без ограничений, вот одна строка на awk :

awk -F : '{x[$7]++;} END {for (k in x) print k": "x[k]}' /etc/passwd

Уроки для изучения здесь:

  • UNIX имеет специализированные инструменты, адаптированные к историческим форматам файлов баз данных. Этот конкретный тип файлов формата является легким для обработки в awk .
  • Вы не должны использовать cat, несмотря на то, что могут сказать инструкторы. Such Существует такая вещь, как чрезмерное использование командных конвейеров. В случае while цикла простое перенаправление будет делать, так как в ответ mnmnc в. В случае с awk файлы для обработки просто задаются в качестве аргументов.
  • Петля в while здесь, конечно, внутри программы awk Его основная функция заключается в последовательном чтении и обработке всех записей во входных файлах, что он делает с помощью цикла.
  • Правильно ли я считаю, что я должен создать переменную для каждого типа оболочки и увеличивать ее каждый раз, когда находит пользователя, который использует эту конкретную оболочку?
    Да, и в однострочнике awk здесь используется так называемый ассоциативный массив, переменная x . Вторая часть скрипта awk показывает обычный способ перебора содержимого такого ассоциативного массива. Первая часть - это просто приращение (оператор постфикса ++) значения одного элемента в массиве, индексируемого седьмым полем записи (которое awk делает доступным как $7).

    Обратите внимание, что вы также можете создавать ассоциативные массивы в сценариях оболочки Bourne Again и адаптировать эту технику к сценарию для ограниченного ответа. Вы можете быть ограничены в использовании while цикла; но никто не заставил вас использовать операторы if .

дальнейшее чтение

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .