Каждое поле в a /etc/passwd
строка разделяется двоеточием, и имя пользователя является первым полем, таким образом, необходимо отфильтровать каждую строку, чтобы только показать символам до первого двоеточия
grep
даже не близко к лучшему инструменту для того, чтобы сделать это, но если Вы будете обязаны использовать его, то это будет работать:
grep -oE '^[^:]+' /etc/passwd
-o
говорит этому только возвращать часть строки, которая соответствует. -E
включает расширенные регулярные выражения так +
будет работать позже. ^
соответствует началу строки, [^:]
соответствия что-либо кроме двоеточия, и +
средства как можно больше символов. Таким образом, это будет соответствовать началу каждой строки вплоть до первого двоеточия
Если Вы можете использовать другие инструменты, кроме того, grep
, вот другие обычно лучшие способы сделать его:
cut -d: -f1 /etc/passwd
sed 's/:.*//' /etc/passwd
awk -F: '{print $1}' /etc/passwd
Можно перенаправить результаты любого из тех, которые в allusers
использование > allusers
как Вы имеют в Вашем примере
Как и ожидалось, это "округление до четного", или "округление банкира".
Ответ на соответствующем сайте объясняет это.
Проблема, которую пытается решить такое правило, заключается в том, что (для чисел с одним десятичным знаком),
Это 4 вниз и 4 вверх.
Чтобы сохранить баланс округления, нам нужно округлить x.5
Это делается по правилу: "Округлить до ближайшего "четного числа"".
В коде:
sh LC_NUMERIC=C printf '%.0f ' "$value"
awk echo "$value" | awk 'printf("%s", $1)'
Всего существует четыре возможных способа округления числа:
Если вам нужно "округлить вверх (в сторону +бесконечное
)", то вы можете использовать awk:
value=195.5
awk echo "$value" | awk '{ printf("%d", $1 + 0.5) }'
bc echo "scale=0; ($value+0. 5)/1" | bc
Если вам все-таки нужно "округлить вниз (В сторону -бесконечного
)", то вы можете использовать:
value=195.5
awk echo "$value" | awk '{ printf("%d", $1 - 0. 5) }'
bc echo "scale=0; ($value-0.5)/1" | bc
Чтобы удалить десятичные знаки (все, что после точки).
Мы также можем напрямую использовать оболочку (работает в большинстве оболочек - это POSIX):
value="127.54" ### Works also for negative numbers.
shell echo "${value%%. *}"
awk echo "$value"| awk '{printf ("%d",$0)}'
bc echo "scale=0; ($value)/1" | bc
Временное изменение режимов округления не такое уж необычное, и это возможно с помощью bin / printf
, хотя не как такового , вам нужно изменить источники.
Вам нужны исходные коды coreutils, я использовал последнюю доступную сегодня версию, которая была http://ftp.gnu.org/gnu/coreutils/coreutils-8.24.tar.xz .
Распакуйте в каталог по вашему выбору с помощью
tar xJfv coreutils-8.24.tar.xz
Перейдите в исходный каталог
cd coreutils-8.24
Загрузите файл src / printf.c
в выбранный вами редактор и замените всю функцию main
следующей функцией, включая обе директивы препроцессора, чтобы включить файлы заголовков math.h
и fenv.h
. Основная функция находится в конце и начинается с int main ...
и заканчивается в самом конце файла закрывающей скобкой }
#include <math.h>
#include <fenv.h>
int
main (int argc, char **argv)
{
char *format;
char *rounding_env;
int args_used;
int rounding_mode;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
exit_status = EXIT_SUCCESS;
posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
// accept rounding modes from an environment variable
if ((rounding_env = getenv ("BIN_PRINTF_ROUNDING_MODE")) != NULL)
{
rounding_mode = atoi(rounding_env);
switch (rounding_mode)
{
case 0:
if (fesetround(FE_TOWARDZERO) != 0)
{
error (0, 0, _("setting rounding mode to roundTowardZero failed"));
return EXIT_FAILURE;
}
break;
case 1:
if (fesetround(FE_TONEAREST) != 0)
{
error (0, 0, _("setting rounding mode to roundTiesToEven failed"));
return EXIT_FAILURE;
}
break;
case 2:
if (fesetround(FE_UPWARD) != 0)
{
error (0, 0, _("setting rounding mode to roundTowardPositive failed"));
return EXIT_FAILURE;
}
break;
case 3:
if (fesetround(FE_DOWNWARD) != 0)
{
error (0, 0, _("setting rounding mode to roundTowardNegative failed"));
return EXIT_FAILURE;
}
break;
default:
error (0, 0, _("setting rounding mode failed for unknown reason"));
return EXIT_FAILURE;
}
}
/* We directly parse options, rather than use parse_long_options, in
order to avoid accepting abbreviations. */
if (argc == 2)
{
if (STREQ (argv[1], "--help"))
usage (EXIT_SUCCESS);
if (STREQ (argv[1], "--version"))
{
version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
(char *) NULL);
return EXIT_SUCCESS;
}
}
/* The above handles --help and --version.
Since there is no other invocation of getopt, handle '--' here. */
if (1 < argc && STREQ (argv[1], "--"))
{
--argc;
++argv;
}
if (argc <= 1)
{
error (0, 0, _("missing operand"));
usage (EXIT_FAILURE);
}
format = argv[1];
argc -= 2;
argv += 2;
do
{
args_used = print_formatted (format, argc, argv);
argc -= args_used;
argv += args_used;
}
while (args_used > 0 && argc > 0);
if (argc > 0)
error (0, 0,
_("warning: ignoring excess arguments, starting with %s"),
quote (argv[0]));
return exit_status;
}
Run ./ configure
следующим образом
LIBS = -lm ./configure --program-suffix = -own
Он помещает суффикс -own
в каждую подпрограмму (их много) на всякий случай, если вы хотите установить их все и не уверены, подходят ли они к остальной системе. Coreutils не названы core utils без причины!
Но наиболее важным является LIBS = -lm
перед строкой. Нам нужна математическая библиотека, и эта команда сообщает ./ configure
, чтобы добавить ее в список необходимых библиотек.
Запустите make
make
Если у вас многоядерная / многопроцессорная система, попробуйте
make -j4
, где число (здесь «4») должно представлять количество ядер, которое вы хотите сэкономить. для этой работы.
Если все прошло хорошо, у вас есть новый printf
int src / printf
. Попробуйте:
BIN_PRINTF_ROUNDING_MODE = 1 ./src/printf '% .0f \ n' 196.5
BIN_PRINTF_ROUNDING_MODE = 2 ./src/printf '% .0f \ n' 196.5
Обе команды должны отличаться выход. Числа после IN_PRINTF_ROUNDING_MODE
означают:
Вы можете установить весь файл (не рекомендуется) или просто скопировать файл (настоятельно рекомендуется переименовать его!) src / printf
в каталог на вашем ] PATH
и используйте, как описано выше.
Это не ошибка, это сделано намеренно.
Он выполняет тип округления до ближайшего (подробнее об этом позже).
При точности .5
мы можем округлять в любую сторону. В школе вам наверняка говорили округлять в большую сторону, но почему? Потому что тогда вам не придется исследовать больше цифр, например, 3,51 округляется до 4; 3,5 можно округлить в любую сторону, но если мы смотрим только на первую цифру и округляем .5 вверх, то всегда получаем правильно.
Однако, если мы рассмотрим набор двузначных десятичных дробей: 0.00 0.01, 0.02, 0.03 ... 0.98, 0.99, то увидим, что существует 100 значений, 1 - целое число, 49 нужно округлить вверх, 49 - вниз, 1 ( 0.50 ) может пойти в любую сторону. Если мы всегда округляем в большую сторону, то в среднем получаем числа, которые на 0,01 больше.
Если мы расширим диапазон до 0 → 9,99, то получим 9 дополнительных значений, которые округляются в большую сторону. Таким образом, наше среднее значение будет немного больше, чем ожидалось. Поэтому одна из попыток исправить это заключается в следующем: .5 округляется в сторону четности. В половине случаев он округляет в большую сторону, в половине случаев - в меньшую.
Это меняет смещение от восходящего к равномерному. В большинстве случаев это лучше.
Вы можете сделать следующий короткий лайнер, если вы действительно хотите округлить от 1 до 4 в меньшую сторону и получить 5 в большую сторону. до x.9.
если [[$ {a # *.} -Ge "5"]]; тогда a = $ (($ {a%. *} + 1)); иначе a = $ {a%.*}; fi
Или замените цифру "5" на любую, например «6».
P.S. относительно проблемы с "." и / или "," в качестве десятичного разделителя (ов), вот простое универсальное решение.
если [[$ {a ## * [.,]} -Ge "5"]]; тогда a = $ (($ {a% [.,] *} + 1)); иначе a = $ {a% [.,] *}; fi