@ Скотт, я знаю, что на этот вопрос уже был дан ответ, но вот несколько комментариев на ваш дополнительный вопрос о разнице между echo $ msg и echo "$ msg". Ваш пример:
nl=$'\n'
msg="Line 1${nl}Line 2"
echo $msg # ouput = Line 1 Line 2
echo -e $msg # ouput = Line 1 Line 2
echo "$msg" # output = Line 1
# Line 2
Это действительно помогает узнать, сколько аргументов оболочка передает команде echo в каждом случае. Эхо принимает любое количество аргументов. Он записывает их все в стандартный вывод, по порядку, с одним пробелом после каждого, кроме последнего.
В первом примере echo $ msg оболочка заменяет $ msg символами, которые вы установили (один из которых - символ новой строки). Затем перед вызовом echo разделяет эту строку на несколько аргументов, используя внутренний разделитель полей (IFS), и передает полученный список аргументов в echo. По умолчанию для IFS заданы пробельные символы (пробелы, табуляции и новые строки), поэтому оболочка разбивает строку $ msg на четыре аргумента: «Строка», «1», «Строка» и «2». Echo даже не видит символ новой строки, потому что оболочка считает его разделителем, как пробел.
Во втором примере echo -e $ msg команда echo получает пять аргументов: "-e", "Line", "1", "Line", "2". Аргумент -e указывает команде расширять любые символы обратной косой черты, которые она видит в своих аргументах, но их нет, поэтому echo оставляет аргументы без изменений. Результат такой же, как в первом примере.
В последнем примере, echo "$ msg", вы говорите оболочке развернуть $msg
и передать ее содержимое в echo , но , чтобы обрабатывать все между двойными кавычками как один аргумент, поэтому echo получает один аргумент - строку, содержащую буквы, цифры, пробелы и символы новой строки. Эта строка повторяет эту строку в точности так, как она ее получает, поэтому «Строка 1» и «Строка 2» отображаются в отдельных строках.
Попробуйте этот эксперимент: установите для IFS нечто произвольное, например букву i, и посмотрите, как оболочка разделяет вашу строку по-разному:
nl=$'\n'
msg="Line 1${nl}Line 2"
IFS=i
echo $msg # ouput = L ne 1
# L ne 2
В пробелах нет ничего особенно волшебного. Здесь из-за странного IFS оболочка обрабатывает букву i как разделитель, но не пробелы или переводы строки. Поэтому echo получает три аргумента: «L», «ne \ nL» и «ne 2». (Я показываю символ новой строки как \ n, но на самом деле это просто один символ, такой как X или p или 5.)
Как только вы поймете, что одинарные и двойные кавычки в командной строке оболочки предназначены для построения аргументов для команд, логика начинает обретать смысл.