Вот как я предлагаю вам сделать это, и я объясню почему, но сначала я хочу поговорить о чем-то еще ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
Многие другие предлагаемые здесь решения, похоже, предполагают, что вы можете каким-то образом повлиять на содержимое переменной оболочки, изменив методы ее расширения. Уверяю вас, это не тот случай.
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
ВЫХОД
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
То, что вы видите выше, это сначала расширение с разделением полей, затем отчет о количестве байтов для исходной переменной расширения, затем расширение с разделителями кавычками и тот же счетчик байтов. Хотя выходные данные могут отличаться, содержимое переменной оболочки $string
никогда не изменяется вообще, кроме как при присваивании.
Более того, если вы не понимаете, почему это так, вы непременно столкнетесь с некоторыми очень неприятными сюрпризами раньше, чем позже. Давайте попробуем это снова, но в немного других условиях.
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
То же самое $string
- другая среда.
ВЫХОД
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
Разделение полей происходит на основе разделителей полей, определенных в $IFS
. Есть два вида разделителей - $IFS
пробелы и $IFS
все остальное. По умолчанию $IFS
назначается новая строка на вкладке пробела - это три возможных $IFS
значения пробела. Однако, как вы можете видеть выше, его легко изменить, и он может оказать радикальное влияние на расщепление полей.
$IFS
пробельные символы будут последовательно перемещаться в одно поле - и именно поэтому echo
расширение, содержащее любую последовательность пробелов, если оно $IFS
содержит пробел, будет вычисляться только в один пробел - потому что echo
объединяет свои аргументы в пробелах. Но любые непробельные значения не будут вытесняться одинаково, и каждый встречающийся разделитель всегда получает поле для себя - как видно из раскрытия материала выше.
Это не самое худшее. Считай это другим $string
.
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
ВЫХОД
* * * * * * 30
* * * * * * 30
Выглядит хорошо, верно? Что ж, давайте снова изменим окружающую среду.
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
ВЫХОД
file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
* * * * * * 30
Ого.
По умолчанию оболочка будет расширять глобусы имен файлов, если она может соответствовать им. Это происходит после раскрытия параметра и разделения поля в его порядке разбора, поэтому любая строка без кавычек уязвима в этом смысле. Вы можете отключить это поведение, set -f
если хотите, но любая POSIX-совместимая оболочка всегда будет по умолчанию.
Это тот тип вещей, с которым вы сталкиваетесь, когда выбрасываете кавычки в расширениях в соответствии со своими предпочтениями отступов. И даже в этом случае, в любом случае, независимо от его поведения расширения, фактическое значение для $string
всегда остается таким, каким оно было при последнем назначении. Итак, вернемся к первому.
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
ВЫХОД
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
Я считаю, что это гораздо более разумный способ адаптации синтаксиса оболочки к вашим предпочтениям отступов. То, что я делаю выше, - это назначение каждой отдельной строки позиционному параметру - на который можно ссылаться по номеру, например, $1
или ${33}
-, а затем присвоение их сцепленных значений с $var
помощью специального параметра оболочки $*
.
Этот подход не застрахован от $IFS
этого. Тем не менее, я считаю, что это связано с $IFS
дополнительным преимуществом в этом отношении. Рассмотреть возможность:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
ВЫХОД
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.
Как видите, $*
объединяет каждый аргумент в "$@"
первом байте $IFS
. Таким образом, при сохранении значения $IFS
по-разному назначаются разные разделители полей для каждого сохраненного значения. Между прочим, вы видите буквальное значение для каждой переменной. Если вы вообще не хотите использовать разделитель, вы должны сделать:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
ВЫХОД
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67