Помощь с переменными и новыми строками, а также цитирование в скрипте bash - PullRequest
4 голосов
/ 07 июня 2010

Я хотел бы автоматизировать следующую команду SVN. Обратите внимание, что эта команда выдает желаемые результаты в моей системе - Ubuntu 10.04, svn 1.6.6, bash shell, когда она запускается из командной строки:

svn ci -m $'Added new File: newFile.txt\nOrig loc: /etc/networking/newFile.txt' /home/user/svnDir/newFile.txt

Я бы хотел выполнить эту команду в bash-скрипте, предполагая, что исходный полный путь к файлу содержится в переменной $ oFileFull, а имя файла - в $ oFileName. Сценарий выполняется из каталога svn. Мне нужно учесть возможность того, что имя файла и / или путь содержат пробелы.

так что строка внутри моего скрипта может выглядеть так:

svn ci -m$'Added new file: ${oFileName}\nOrig loc: ${oFileFull}' ${oFileName}

Но я хочу, чтобы переменные (которые могут содержать пробелы) были расширены до выполнения команды, и я не могу понять, как это сделать, заключив комментарий svn в одинарные кавычки, что необходимо для получения новой строки в журнал комментариев Subversion. Я дергаю себя за волосы, пытаясь понять, как правильно процитировать и собрать эту команду. Любая помощь приветствуется.

Ответы [ 4 ]

7 голосов
/ 08 июня 2010

@ Скотт, я знаю, что на этот вопрос уже был дан ответ, но вот несколько комментариев на ваш дополнительный вопрос о разнице между 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.)

Как только вы поймете, что одинарные и двойные кавычки в командной строке оболочки предназначены для построения аргументов для команд, логика начинает обретать смысл.

5 голосов
/ 07 июня 2010

Поместите новую строку в переменную, используйте переменную везде, где вам нужна новая строка, и измените кавычки вокруг вашей большей строки на двойные кавычки. Вы также должны всегда заключать в кавычки любую переменную, которая содержит имя файла.

nl=$'\n'
svn ci -m"Added new file: ${oFileName}${nl}Orig loc: ${oFileFull}" "${oFileName}"
0 голосов
/ 08 июня 2010

Bash объединит смежные кавычки.Например,

$ r=rooty
$ t=tooty
$ echo $r$'\n'$t
rooty
tooty
$ echo "$r $r"$'\n'$t
rooty rooty
tooty

Для интерактивного руководства может оказаться полезным расширенное руководство по написанию сценариев bash, хотя оно может быть не лучше, чем просто чтение подробного и подробного руководства bash.Я рекомендую использовать команду Man vim (стандартно для версии 7.2, если не в более ранних версиях), чтобы вызвать руководство по bash, а затем использовать сворачивание на основе отступов, чтобы вы могли просмотреть его иерархию.Что ж, при условии, что у вас нет времени и терпения, чтобы прочитать все 3300 строк от начала до конца.

0 голосов
/ 07 июня 2010

@ Деннис:

Ого, мне сложно обернуть голову, я бы с удовольствием, если бы кто-то мог указать мне на онлайн-ресурс, который объясняет это ясно и кратко. Те, что я нашел, не прояснили это для меня.

Мой последний источник путаницы заключается в следующем:

#!/bin/bash
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

То, что я пытаюсь проиллюстрировать, состоит в том, что двойные кавычки вокруг переменной $ msg разбивают вывод на две строки, без двойных кавычек, даже с ключом -e новой строки нет.

Я не понимаю, почему нужны двойные кавычки - почему переменная $ nl не раскрывается, когда она назначается как часть переменной msg?

Надеюсь, я не совершу фиктивную ошибку StackOverflow, отвечая на мой собственный вопрос. И на самом деле я не даю ответ, а просто отвечаю на ваш комментарий. Я не могу отформатировать комментарий по мере необходимости.

...