Как разделить строку по содержимому - PullRequest
0 голосов
/ 20 мая 2019

У меня есть строка в общем шаблоне, которой я хочу манипулировать. Я хочу иметь возможность превратить строку 5B299 в 5B300 (увеличить последнее число на единицу).

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

Единственные вещи, которые я нашел в Интернете, покажут мне, как вырезать разделителем, но у меня нет постоянного разделителя.

Ответы [ 3 ]

2 голосов
/ 20 мая 2019

Вы можете довольно легко делать то, что вы пытаетесь, используя bash параметр-расширение для строковых индексов вместе с арифметическим оператором POSIX. Например, вы можете сделать:

#!/bin/bash

[ -z "$1" ] && {    ## validate at least 1 argument provided
    printf "error: please provide a number.\n" >&2
    exit 1
}

[[ $1 =~ [^0-9][^0-9]* ]] && {  ## validate all digits in argument
    printf "error: input contains non-digit characters.\n" >&2
    exit 1
}

suffix=${1:1}           ## take all character past 1st as suffix
suffix=$((suffix + 1))  ## increment suffix by 1

result=${1:0:1}$suffix  ## append suffent to orginal 1st character
echo "$result"          ## output

exit 0

, который оставит 1-й символ в одиночку при увеличении оставшихся символов на 1 и последующем объединении с исходной 1-й цифрой, подтверждая, что ввод состоит только из цифр, например,

Пример использования / Вывод

$ bash prefixsuffix.sh
error: please provide a number.

$ bash prefixsuffix.sh 38a900
error: input contains non-digit characters.

$ bash prefixsuffix.sh 38900
38901

$ bash prefixsuffix.sh 39999
310000

Посмотрите вещи и дайте мне знать, если это то, что вы хотели.

2 голосов
/ 20 мая 2019

Вы можете использовать функции регулярных выражений, поддерживаемые оболочкой bash с ее конструкцией ~, которая поддерживает базовое сопоставление расширенных регулярных выражений (ERE).Все, что вам нужно сделать, это определить регулярное выражение и поработать с захваченными группами, чтобы получить результирующую строку

str=5B299
re='^(.*[A-Z])([0-9]+)$' 

Теперь используйте оператор ~ для сопоставления с регулярным выражением.Оператор ~ заполняет массив BASH_REMATCH захваченными группами, если совпадение с регулярным выражением прошло успешно.Первая часть (5B в примере) будет сохранена в индексе 0, а следующая - в 1.Мы увеличиваем значение по индексу 1 с помощью оператора $((..)).

if [[ $str =~ $re ]]; then
    result="${BASH_REMATCH[1]}$(( BASH_REMATCH[2] + 1 ))"
    printf '%s\n' "$result"
fi

Версия регулярного выражения POSIX, свободная от зависимости от локали, будет использовать классы символов вместо выражений диапазона как

posix_re='^(.*[[:alpha:]])([[:digit:]]+)$'
1 голос
/ 20 мая 2019

Вы можете использовать sed в сочетании с awk:

increment() {
   echo $1 | sed -r 's/([0-9]+[a-zA-Z]+)([0-9]+)/\1 \2/' | awk '{printf "%s%d", $1, ++$2}'
}

echo $(increment "5B299")
echo $(increment "127ABC385")
echo $(increment "7cf999")

Выход:

5B300
127ABC386
7cf1000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...