Implementing an extended regexp to add a variable number of leading zeros based on position in a string

Одним из возможных решений является использование универсального формата диска (UDF). UDF поддерживает тома объемом 2 терабайта, длинные имена файлов и разрешения файлов POSIX. UDF используется на дисках DVD и Blu-ray, но, вопреки распространенному мнению, также может использоваться в качестве формата файловой системы на жестких дисках и съемных флэш-накопителях.

Я не очень хорошо знаком с FreeBSD, поэтому не уверен, что поддержка записи реализована в этой системе.

10
20.07.2017, 07:37
5 ответов

Использование:leading_zero.sh input.txt

#!/bin/bash

sed -r '
    s/\.([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{1,3},)/.0\1.0\2.00\3/
    s/\.0*([0-9]{2})\.0*([0-9]{2})\.0*([0-9]{3})/.\1.\2.\3/
' "$1"

Пояснение:

  1. Первая подстановка добавляет к каждому числу определенное количество нулей. 1 ноль к 2 и 3 цифрам, 2 ноль к 4 цифре. Неважно, сколько уже цифр.
  2. Вторая подстановка удаляет все лишние нули, оставляя только необходимое количество чисел. 2 и 3 номера должны содержать только 2 цифры. Оставляет их и удаляет остатки. Четвертый номер должен содержать только 3 цифры. Оставляет их и удаляет остатки.

input.txt

1.1.1.1,Some Text Here
1.1.1.1,Some Text Here
1.11.1.11,Some Text Referring to Document XXX Heading 1.2.3
1.1.1.1,Some Text Here
1.1.11.111,Some Text Referring to Document XXX Heading 1.2.3
1.11.1.1,Some Text Here

вывод.txt

1.01.01.001,Some Text Here
1.01.01.001,Some Text Here
1.11.01.011,Some Text Referring to Document XXX Heading 1.2.3
1.01.01.001,Some Text Here
1.01.11.111,Some Text Referring to Document XXX Heading 1.2.3
1.11.01.001,Some Text Here
4
27.01.2020, 20:00

Вот один из возможных подходов:
sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'

Примеры

echo "1.11.111.1111,Some Text Here" | sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'
1.011.0111.001111,Some Text Here

Также работайте с этой строкой:

echo "1.1.1.1,Some Number 1 Here" | sed -E 's/([0-9]\.)/0\1/g;s/.//;s/([0-9],)/00\1/'
1.01.01.001,Some Number 1 Here

...и эта строка:

echo "1.2.2101.7191,Some Text Here" | sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'
1.02.02101.007191,Some Text Here
3
27.01.2020, 20:00

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

Сначала вот один -вкладыш:

(
    echo '1.2.3.4,Some Text Here'
    echo '1.01.01.1,Some Text Here'
    echo '1.1.1.1,Some Number 1 Here'
    echo '1.1.1.1,Some Text Referring to Document XXX Heading 1.2.3'
    echo '1.2.3.4,Some \n \s \text'
) |
perl -ne '($ip, $text) = split(/,/, $_, 2); $ip = sprintf("%1d.%02d.%03d.%03d", split(/\./, $ip)); print "$ip,$text"'

Его результаты:

1.02.003.004,Some Text Here
1.01.001.001,Some Text Here
1.01.001.001,Some Number 1 Here
1.01.001.001,Some Text Referring to Document XXX Heading 1.2.3
1.02.003.004,Some \n \s \text

А вот perlскрипт разбит и прокомментирован (флаг -nсоздает неявный while read; do... doneцикл вокруг кода):

($ip, $text) = split(/,/, $_, 2);                # Split line into two parts by comma
@octets = split(/\./, $ip)                       # Split IP address into octets by dots
$ip = sprintf("%1d.%02d.%03d.%03d", @octets);    # Apply the formatting
print "$ip,$text"                                # Output the two parts
5
27.01.2020, 20:00

bash может справиться с этим. Однако это будет намного медленнее, чем Perl:

echo "1.1.1.1,Some Text Here" | 
while IFS=., read -r a b c d text; do
    printf "%d.%02d.%02d.%03d,%s\n" "$a" "$b" "$c" "$d" "$text"
done
1.01.01.001,Some Text Here
9
27.01.2020, 20:00
perl -pe '/^\d/g && s/\G(?:(\.\K\d+(?=\.))|\.\K\d+(?=,))/sprintf "%0".($1?2:3)."d",$&/ge'

Пояснение:

Используемый здесь метод заключается в просмотре окрестностей числовых значений и выполнении действий на их основе. Таким образом, 2-е и 3-е числа видят точку с обеих сторон, в то время как 4-е число видит точку слева и запятую справа.

$1 устанавливается, когда регулярное выражение выбирает путь 2-го или 3-го числа и, соответственно, точность заполнения равна 2. OTOH, для 4-го числа заполнение равно 3.

%cat файл.txt

1.00.3.4,Some Text Here
1.01.01.1,Some Text Here
1.0.01.1,Some Number 1 Here
1.1.1.1,Some Text Referring to Document XXX Heading 1.2.3.4
1.2.3.4,Some \n \s \text

Результаты:

1.00.03.004,Some Text Here
1.01.01.001,Some Text Here
1.00.01.001,Some Number 1 Here
1.01.01.001,Some Text Referring to Document XXX Heading 1.2.3.4
1.02.03.004,Some \n \s \text
2
27.01.2020, 20:00

Теги

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