Ось як я пропоную вам це зробити, і я поясню чому, але спершу я хочу поговорити про щось інше ...
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
пробілу значень newline - це три можливі значення пробілу. Це легко змінюється, хоча, як ви бачите вище, і може мати різкий вплив на розширення по полях.
$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