Как разбить одну строку на несколько переменных в оболочке bash?

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

В настоящее время переменная устанавливается на что-то вроде строки:
ABCDE-123456
и я хотел бы разбить это на 2 переменные, исключив " -". т.е.:
var1=ABCDE
var2=123456

Как это можно сделать?


Это решение, которое сработало для меня:
var1=$(echo $STR | cut -f1 -d-)
var2=$(echo $STR | cut -f2 -d-)

Можно ли использовать команду cut, которая будет работать без разделителя (каждый символ будет установлен как переменная)?

var1=$(echo $STR | cut -f1 -d?)
var2=$(echo $STR | cut -f1 -d?)
var3=$(echo $STR | cut -f1 -d?)
etc.

Ответ 1

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

var1=$(echo $STR | cut -f1 -d-)
var2=$(echo $STR | cut -f2 -d-)

Я выбрал cut здесь, потому что вы могли бы просто расширить код еще на несколько переменных...

Ответ 2

read с IFS идеально подходят для этого:

$ IFS=- read var1 var2 <<< ABCDE-123456
$ echo "$var1"
ABCDE
$ echo "$var2"
123456

Edit:

Вот как вы можете прочитать каждый отдельный символ в элементах массива:

$ read -a foo <<<"$(echo "ABCDE-123456" | sed 's/./& /g')"

Дамп массива:

$ declare -p foo
declare -a foo='([0]="A" [1]="B" [2]="C" [3]="D" [4]="E" [5]="-" [6]="1" [7]="2" [8]="3" [9]="4" [10]="5" [11]="6")'

Если в строке есть пробелы:

$ IFS=$'\v' read -a foo <<<"$(echo "ABCDE 123456" | sed 's/./&\v/g')"
$ declare -p foo
declare -a foo='([0]="A" [1]="B" [2]="C" [3]="D" [4]="E" [5]=" " [6]="1" [7]="2" [8]="3" [9]="4" [10]="5" [11]="6")'

Ответ 3

Если вы знаете, что это будет всего лишь два поля, вы можете пропустить дополнительные подпроцессы следующим образом:

var1=${STR%-*}
var2=${STR#*-}

Что это делает? ${STR%-*} удаляет кратчайшую подстроку $STR, которая соответствует шаблону -*, начиная с конца строки. ${STR#*-} делает то же самое, но с шаблоном *- и начинается с начала строки. У каждого из них есть экземпляры %% и ##, которые находят самый длинный привязанный шаблон. Если у кого-то есть полезная мнемоника, чтобы помнить, что делает, что, дайте мне знать! Мне всегда нужно стараться запомнить оба.

Ответ 4

Звучит как задание для set с пользовательским IFS.

IFS=-
set $STR
var1=$1
var2=$2

(Вам нужно сделать это с помощью функции local IFS, чтобы вы не испортили другие части вашего script, где вам нужно IFS, чтобы вы ожидали.)

Ответ 5

Использование возможностей bash regex:

re="^([^-]+)-(.*)$"
[[ "ABCDE-123456" =~ $re ]] && var1="${BASH_REMATCH[1]}" && var2="${BASH_REMATCH[2]}"
echo $var1
echo $var2

OUTPUT

ABCDE
123456

Ответ 6

string="ABCDE-123456"
IFS=- # use "local IFS=-" inside the function
set $string
echo $1 # >>> ABCDE
echo $2 # >>> 123456