CLI: увеличить число в строке, сохраняя дополненные нули - PullRequest
1 голос
/ 06 июля 2019

В настоящее время я использую эту команду perl для увеличения последнего числа в строке:

perl -pe 's/(\d+)(?!.*\d+)/$1+1/e' <<< "abc123_00456.txt"

Он выводит abc123_457.txt, а я хочу abc123_00457.txt.

Я также хочу, чтобы что-то вроде 99 увеличилось до 100, хотя, если это слишком сложно, 00 также приемлемо.

Еще несколько примеров того, что я хочу:

09 -> 10
004 -> 005

Я также хочу иметь возможность увеличиваться на любое число (не только на 1), поэтому нет ++.

Я не хочу использовать встроенные функции оболочки для этого.

Ответы [ 4 ]

5 голосов
/ 06 июля 2019

Попробуйте:

perl -pe 's/(\d+)(?=\D*\z)/my $n = $1; ++$n/e' <<< "abc123_00456.txt"

Оператор ++ сохраняет число цифр при увеличении строки.

В качестве альтернативы:

perl -pe 's/(\d+)(?=\D*\z)/sprintf "%0*d", length($1), $1 + 1/e' <<< "abc123_00456.txt"

Это позволяет увеличивать более чем на 1 (или выполнять другие арифметические операции).

sprintf %d форматирует целое число в десятичном формате.0 означает заполнить результат нулями;* означает, что максимальная ширина поля берется из следующего аргумента вместо самой строки формата.(Например, %05d означает «отформатировать число, заполнив его нулями до ширины не менее 5 символов».)

Здесь мы просто берем длину исходной строки цифр (length($1)) ииспользуйте это как ширину нашего поля.Число для форматирования $1 + 1.Если она короче исходной строки, sprintf автоматически добавляет нули.

См. Также perldoc -f sprintf.

3 голосов
/ 06 июля 2019

Вы можете использовать отформатированную строку с sprintf:

perl -pe 's/(\d+)(?!.*\d)/sprintf("%05d",$1+1)/e' <<< "abc123_00456.txt"

5 - ширина вашего номера, 0 - это символ, используемый для заполнения номера.

ДляПо неизвестной ширине вы можете построить динамически отформатированную строку:

perl -pe 's/(\d+)(?!.*\d)/sprintf("%0".length($1)."d",$1+1)/e' <<< "abc123_00456.txt"
2 голосов
/ 06 июля 2019

С GNU awk для сопоставления 3-го аргумента ():

$ awk -v n=17 'match($0,/(.*[^0-9])([0-9]+)(.*)/,a){$0=a[1] sprintf("%0*d",length(a[2]),a[2]+n) a[3]} 1' <<< "abc123_00456.txt"
abc123_00473.txt

С любым awk в любой оболочке на каждой коробке UNIX:

$ awk -v n=17 'match($0,/[0-9]+\./){lgth=RLENGTH-1; tgt=substr($0,RSTART,lgth); $0=substr($0,1,RSTART-1) sprintf("%0*d",lgth,tgt+n) substr($0,RSTART+lgth)} 1' <<< "abc123_00456.txt"
abc123_00473.txt
0 голосов
/ 07 июля 2019

Это может работать для вас (GNU sed & Bash):

sed -E 's/^([^0-9]*([0-9]+[^0-9]+)*0*)([0-9]+)(.*)/echo "\1$((\3+1))\4"/e' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...