Как разбить одну строку на несколько переменных в оболочке 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