Как извлечь наибольшее значение UID из /etc/passwd?
Я хочу предсказать следующий UID перед созданием нового пользователя. Поскольку новый примет самое большое значение идентификатора и добавит к нему 1, я подумал о следующем сценарии:
biggestID=0
cat /etc/passwd | while read line
do
if test [$(echo $line | cut -d: -f3) > $biggestID]
then
biggestID=$(echo $line | cut -d: -f3)
fi
echo $biggestID
done
let biggestID=$biggestID+1
echo $biggestID
В результате я получаю 1
, Это смутило меня, и я подумал, что проблема с циклом, поэтому я добавил echo $biggestID
ниже fi
чтобы проверить, действительно ли меняется его значение, и выясняется, что с циклом проблем нет, так как я получил много значений до 1000. Так почему biggestID
возвращаемое значение 0
после цикла?
3 ответа
Это из-за этой строки:
cat /etc/passwd | while read line
Это работает while
цикл в под-оболочке, так biggestID
устанавливается в вложенной оболочке, а не в родительской оболочке.
Если вы измените ваш цикл следующим образом, он будет работать:
while read line
...
done < /etc/passwd
Это потому что while
цикл теперь выполняется в той же оболочке, что и основной скрипт, и вы просто перенаправляете содержимое /etc/passwd
в петлю.
Вы можете изменить программу на что-то вроде этого:
newID=$(( $(cut -d: -f3 /etc/passwd | sort -n | tail -n 1 ) +1 ))
echo $newID
cut -d: -f3 /etc/passwd| sort -n | tail -n 1
извлекает наибольшее значение из третьего поля в passwd$( ... )
обозначает результат команды, здесь самый большой идентификаторnewID=$(( ... + 1 ))
добавить 1 и сохранить результат в newID
С помощью awk вы делаете все расчеты в одной программе:
awk -F: 'BEGIN {maxuid=0;} {if ($3 > maxuid) maxuid=$3;} END {print maxuid+1;}' /etc/passwd
Если вы не хотите начинать с awk, оставьте отзыв о вашем коде.
biggestID=0
# Do not use cat .. but while .. do .. done < input (do not open subshell)
# Use read -r line (so line is taken literally)
cat /etc/passwd | while read line
do
# Do not calculate the uid twice (in test and assignment) but store in var
# uid=$(cut -d: -f3 <<< "${line}")
# Use space after "[" and before "]"
# test is not needed, if [ .. ] already implicit says so
# (I only use test for onelines like "test -f file || errorfunction")
if test [$(echo $line | cut -d: -f3) > $biggestID]
then
biggestID=$(echo $line | cut -d: -f3)
fi
# Next line only for debugging
echo $biggestID
done
# You can use (( biggestID = biggestID + 1 ))
# or (when adding one)
# (( ++biggestID ))
let biggestID=$biggestID+1
# Use double quotes to get the contents literally, and curly brackets
# for a nice style (nothing strang will happen if you add _happy right after the var)
# echo "${biggestID}"
echo $biggestID