Одним из возможных решений является использование универсального формата диска (UDF). UDF поддерживает тома объемом 2 терабайта, длинные имена файлов и разрешения файлов POSIX. UDF используется на дисках DVD и Blu-ray, но, вопреки распространенному мнению, также может использоваться в качестве формата файловой системы на жестких дисках и съемных флэш-накопителях.
Я не очень хорошо знаком с FreeBSD, поэтому не уверен, что поддержка записи реализована в этой системе.
Использование: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"
Пояснение:
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
Вот один из возможных подходов: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
Вы специально не просили 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
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
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