Добавьте тысячи разделителя в числе

У меня есть сценарий в моем .vimrc который делает точно это. Однако это делает так для всех файлов, открытых, который имеет swp файл. Не уверенный, если Вы всегда хотите это поведение. Возможно, можно настроить его для приспосабливания потребностей в макросе, который Вы пишете.

Для открытия ro, если swp файл присутствует, вставляет это Ваш .vimrc:

func CheckSwap()
  swapname
  if v:statusmsg =~ '\.sw[^p]$'
    set ro
  endif
endfunc

if &swf
  set shm+=A
  au BufReadPre * call CheckSwap()
endif

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

40
07.02.2014, 00:04
11 ответов

С sed:

$ echo "123456789" | sed 's/\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)/\1,\2,\3/g'
123,456,789

(Обратите внимание, что это только работает точно на 9 цифр!)

или это с sed:

$ echo "123456789" | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'
123,456,789

С printf:

$ LC_NUMERIC=en_US printf "%'.f\n" 123456789
123,456,789
32
27.01.2020, 19:35
  • 1
    , которые я также пробую awk, но это, добавляет запятая в последнем echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g")' –  Rahul Patil 06.02.2014, 09:56
  • 2
    теперь, который я получаю, но это, кажется сложным echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g"){sub(",$",""); print}' –  Rahul Patil 06.02.2014, 10:07
  • 3
    Это сначала sed только работы, если число является точно 9 цифрами. printf не работает над zsh. Таким образом второе sed ответ является, вероятно, лучшим. –  Patrick 06.02.2014, 15:51
  • 4
    @RahulPatil, Который только работает правильно, если количество цифр трехзначного порядка. Попробуйте "12345678", и Вы будете видеть то, что я имею в виду. заголовок –  Patrick 06.02.2014, 15:52
  • 5
    Можно сделать echo 123456789 | awk '{printf ("%'\''d\n", $0)}' (который очевидно не всегда работает над Linux!?, но хорошо работает на AIX и Солярисе), –  Johan 28.11.2014, 11:36

bash printf поддержки в значительной степени все можно выполнить printf C функция

type printf           # => printf is a shell builtin
printf "%'d" 123456   # => 123,456

printf от coreutils сделает то же

/usr/bin/printf "%'d" 1234567   # => 1,234,567
53
27.01.2020, 19:35
  • 1
    Это теперь поддерживается в zsh также, обновленное сообщение здесь. –  don_crissti 13.12.2015, 21:55
  • 2
    я нахожусь на ударе 4.1.2 и он не поддерживает... :( –  msb 31.01.2017, 21:19
  • 3
    @msb Это, кажется, зависит от Вашей системы vsnprintf. В системе GNU/Linux glibc, кажется, поддерживал его с тех пор, по крайней мере, 1995. –  Mikel 01.02.2017, 03:50
  • 4
    printf, использует тысячи разделителя для Вашей текущей локали, которая могла бы быть запятой, точкой или ничем вообще. Вы можете export LC_NUMERIC="en_US" если Вы хотите вызвать запятые. –  medmunds 27.03.2017, 21:31

awk и bash имеют хорошие встроенные решения, основанные на printf , как описано в других ответах. Но сначала sed .

Для sed нам нужно сделать это «вручную». Общее правило состоит в том, что если у вас есть четыре последовательных цифры, за которыми следует нецифровая (или конец строки), то между первой и второй цифрами следует вставить запятую.

Например,

echo 12345678 | sed -re 's/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/'

напечатает

12345,678

Нам, очевидно, нужно затем повторить процесс, чтобы продолжать добавлять достаточно запятых.

sed -re ' :restart ; s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/ ; t restart '

В sed команда t указывает метку, к которой будет выполнен переход, если последняя команда s /// была успешной. Поэтому я определяю метку с помощью : restart , чтобы она возвращалась назад.

Вот демонстрация bash (на ideone ), которая работает с любым количеством цифр:

function thousands {
    sed -re ' :restart ; s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/ ; t restart '
}                                                 
echo 12 | thousands
echo 1234 | thousands
echo 123456 | thousands
echo 1234567 | thousands
echo 123456789 | thousands
echo 1234567890 | thousands
2
27.01.2020, 19:35

С некоторыми реализациями awk :

echo "123456789" | awk '{ printf("%'"'"'d\n",$1); }'  

123,456,789  

"% '"' "'d \ n" is: "% (одинарная кавычка) (двойная кавычка) ( одинарная кавычка) (двойная кавычка) (одинарная кавычка) d \ n "

Будет использоваться настроенный разделитель тысяч для вашей локали (обычно , в английских локали, пробел во французском, . на испанском / немецком ...). То же, что и localeousand_sep

3
27.01.2020, 19:35
$ echo 1232323 | awk '{printf(fmt,$1)}' fmt="%'6.3f\n"
12,32,323.000
1
27.01.2020, 19:35

También quería tener la parte después de el separador decimal correctamente separado/espaciado, por lo tanto, escribí este script sed -que usa algunas variables de shell para ajustarse a la región y preferencias personales. También tiene en cuenta diferentes convenciones para el número de dígitos agrupados:

#DECIMALSEP='\.' # usa                                                                                                               
DECIMALSEP=','   # europe
    
#THOUSSEP=','  # usa
#THOUSSEP='\.' # europe
#THOUSSEP='_'  # underscore
#THOUSSEP=' '  # space
THOUSSEP=' '   # thinspace
    
# group before decimal separator
#GROUPBEFDS=4   # china
GROUPBEFDS=3    # europe and usa
    
# group after decimal separator
#GROUPAFTDS=5   # used by many publications 
GROUPAFTDS=3
    
    
function digitgrouping {
# FIXME: This is a workaround: BEGINNING has to be marked (and after                                                                
# alteration removed) for the first number to be spaced correctly (1234
# should be 1 234, and that only works if something is in front of that
# number).
sed -e 's%^%BEGINNING&%' \
  -e '
  s%\([0-9'"$DECIMALSEP"']\+\)'"$THOUSSEP"'%\1__HIDETHOUSSEP__%g
  :restartA ; s%\([0-9]\)\([0-9]\{'"$GROUPBEFDS"'\}\)\(['"$DECIMALSEP$THOUSSEP"']\)%\1'"$THOUSSEP"'\2\3% ; t restartA
  :restartB ; s%\('"$DECIMALSEP"'\([0-9]\{'"$GROUPAFTDS"'\}\'"$THOUSSEP"'\)*\)\([0-9]\{'"$GROUPAFTDS"'\}\)\([0-9]\)%\1\3'"$THOUSSEP"'\4% ; t restartB
  :restartC ; s%\([^'"$DECIMALSEP"'][0-9]\+\)\([0-9]\{'"$GROUPBEFDS"'\}\)\($\|[^0-9]\)%\1'"$THOUSSEP"'\2\3% ; t restartC
  s%__HIDETHOUSSEP__%\'"$THOUSSEP"'%g' \
  -e 's%^BEGINNING%%'

}
0
27.01.2020, 19:35
a="13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096"

echo "$a" | rev | sed "s#[[:digit:]]\{3\}#&,#g" | rev

13,407,807,929,942,597,099,574,024,998,205,846,127,479,365,820,592,393,377,723,561,443,721,764,030,073,546,976,801,874,298,166,903,427,690,031,858,186,486,050,853,753,882,811,946,569,946,433,649,006,084,096
1
27.01.2020, 19:35

Обычный вариант использования для меня — изменить вывод конвейера команд так, чтобы десятичные числа печатались с разделителями тысяч. Вместо того, чтобы писать функцию или сценарий, я предпочитаю использовать метод, который я могу настроить на лету для любого вывода из конвейера Unix.

Я обнаружил, что printf(, предоставленный Awk ), является наиболее гибким и запоминающимся способом достижения этой цели. Символ апострофа/одинарной кавычки определяется POSIX как модификатор для форматирования десятичных чисел и имеет то преимущество, что он учитывает локаль -, поэтому он не ограничен использованием запятых.

При выполнении команд Awk из оболочки Unix могут возникнуть трудности с вводом одиночной -кавычки внутри строки, ограниченной одинарными -кавычками (, чтобы избежать расширения оболочки позиционных переменных, например,$1). В этом случае я считаю, что наиболее читаемый и надежный способ ввести одинарную кавычку -— это ввести ее как восьмеричную управляющую последовательность (, начинающуюся с\0).

Пример:

printf "first 1000\nsecond 10000000\n" |
  awk '{printf "%9s: %11\047d\n", $1, $2}'
  first:       1,000
 second:  10,000,000

Имитация вывода конвейера, показывающая, какие каталоги используют больше всего дискового пространства:

printf "7654321 /home/export\n110384 /home/incoming\n" |
  awk '{printf "%22s: %9\047d\n", $2, $1}'
  /home/export: 7,654,321
/home/incoming:   110,384

Другие решения перечислены в Как избежать одинарной кавычки внутри awk .

Примечание :, как указано в Print a Single Quote , рекомендуется избегать использования шестнадцатеричных escape-последовательностей, поскольку они не работают надежно в разных системах.

2
27.01.2020, 19:35

Решение bash/awk(по запросу ), которое работает независимо от длины числа и использует ,независимо от настройки thousands_sepлокали, а также везде, где числа находятся на входе, и избегает добавление разделителя тысяч после в1.12345:

echo not number 123456789012345678901234567890 1234.56789 |
  awk '{while (match($0, /(^|[^.0123456789])[0123456789]{4,}/))
        $0 = substr($0, 1, RSTART+RLENGTH-4) "," substr($0, RSTART+RLENGTH-3)
        print}'

Дает:

not number 123,456,789,012,345,678,901,234,567,890 1,234.56789

В реализациях awk, таких как mawk, которые не поддерживают операторы интервальных регулярных выражений, измените регулярное выражение на/(^|[^.0123456789])[0123456789][0123456789][0123456789][0123456789]+/

0
27.01.2020, 19:35

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

echo "1000066955"|sed -rn "s/([[:digit:]])([[:digit:]]{3})$/\1 \2/;T end;:loop s/([[:digit:]])([[:digit:]]{3})[[:space:]]/\1 \2 /;t loop;:end p;"
0
23.06.2021, 15:51
= Number grouping formatting using Perl RegEx =

[
|*| Source: https://unix.stackexchange.com/a/656655
|*| Last update: CE 2021-08-18 06:44 UTC ]


Number grouping formatting (e.g. turning "1000000" into "1,000,000"; approximation of `numfmt --grouping`) using Perl RegEx:
(Unix Shell)
[
    PERLIO=':raw:utf8' exec '/usr/bin/perl' -p \
    -e 'BEGIN { $^H |= 0x02800000; $^H{reflags_charset} = 4; $/ = undef(); }' \
    -e '

    sub f {
    $x1 = $1;
    $x2 = $2;
#
# [
    if ( length( $x1 ) > 3 ) {
    pos( $x1 ) = length( $x1 ) % 3;
    $x1 =~ s/\G.{3}/ ( pos( $x1 ) != 0 ? "," : "" ).${&}; /gse;
    };
# ]
#
# Would work but inefficient:
# [
#   $x1 =~ s/(?<=\d)(?=(\d+))/ ( length( $1 ) % 3 != 0 ? "" : "," ); /ge;
# ]
#,
# [
#   $x1 =~ s/(?<=\d)(?=(?:\d{3})+(?!\d))/,/g;
# ]
#
    "${x1}${x2}";
    };

    s/(?<![\w#&)*,.\/:;=-\@\[-\]`{-}])([0-9]+)(\.[0-9]+)?(?![\w#\$&(*\-\/<=\@\[-\]`{-}]|\.[^\W0-9])/ f(); /geu;

    ' \
    "$@";
]
[ Explanation Needed ]


Test case:
(Console Log (Unix) )
[
> \
    { nf <<\EOF
0.000000
10.000000
100.000000
1000.000000
10000.000000
100000.000000
1000000.000000
10000000.000000
100000000.000000
1000000000.000000
10000000000.000000
100000000000.000000
1000000000000.000000
EOF
    } | nf; # Verified idempotence.

0.000000
10.000000
100.000000
1,000.000000
10,000.000000
100,000.000000
1,000,000.000000
10,000,000.000000
100,000,000.000000
1,000,000,000.000000
10,000,000,000.000000
100,000,000,000.000000
1,000,000,000,000.000000
]
[ Alternatively: Try the full text of this message. ]




See also:
|*| "perlrun" - how to execute the Perl interpreter # "-i''[extension]''": https://perldoc.perl.org/perlrun#-i%5Bextension%5D
0
01.07.2021, 23:48

Теги

Похожие вопросы