Почти во всех инструкциях PowerShell используются строковые значения. Обычно они передаются командам в качестве аргументов. В одних случаях строковые значения заключаются в одинарные кавычки, в других — в двойные, а иногда и вовсе используются без кавычек. Важно понимать, как правильно работать с кавычками. Правила, регулирующие эту работу, часто называют правилами заключения в кавычки. На сегодняшнем уроке речь пойдет об этих правилах. В частности, я расскажу о том, когда необходимо заключать строковые значения в кавычки и какие кавычки использовать — двойные или одинарные, а также о том, как маркируются, или экранируются, специальные символы.

Работа со строковыми значениями

Всякий раз, когда текст заключается в кавычки, PowerShell рассматривает его как строковое значение. Поэтому, если только текст не содержит специальных символов (ими мы займемся очень скоро) или переменных ссылочного типа (речь о таких переменных пойдет на следующем уроке), такой текст можно заключать в одинарные либо в двойные кавычки. Так, следующие инструкции дают идентичные результаты:

Write-Output "String in quotes."
Write-Output 'String in quotes.'

В приведенных примерах команда Write-Output направляет строковый объект в конвейер, а в данном случае — непосредственно на консоль PowerShell. Как показано на экране 1, обе инструкции имеют одно и то же выходное значение.

 

Чтобы вывести данные на консоль, можно использовать не только Write-Output, но и реализованные в PowerShell команды Out-Host, а также Write-Host. Различия между ними в деталях. Так, команда Write-Output направляет выходные данные по конвейеру следующей команде. Когда же Write-Output является последней командой в конвейере, ее выходные данные отображаются в консоли. Команда Out-Host направляет свои выходные данные непосредственно на консоль. Она имеет необязательный параметр, который позволяет просматривать выходные данные поэкранно, что полезно при больших объемах выходных данных. Out-Host используется в качестве выходной команды по умолчанию, поэтому если вы не указываете, какая команда является выходной, применяется именно она. Команда Write-Host тоже направляет выходные данные непосредственно на консоль. Но она имеет два необязательных параметра, которые дают возможность изменять цвет текста или фона, на котором отображается текст, что позволяет настраивать консоль в соответствии с пожеланиями пользователя.

При использовании заключенных в кавычки базовых строковых значений, которые передаются непосредственно в окно консоли, все три команды ведут себя одинаково. К примеру, все четыре публикуемые ниже команды отображают строку в окне консоли так, как показано на экране 1:

"String in quotes."
Write-Output "String in quotes."
Write-Host "String in quotes."
Out-Host ` – InputObject "String in quotes".

Обратите внимание: в первой команде глагол не указан. В результате используется команда Out-Host.

Надо сказать, что во многих приводимых в статье примерах я использую команду Write-Output, поскольку она работает с выходным объектом так же, как и многие другие команды. Так я получаю возможность продемонстрировать различные принципы, применяемые в отношении заключенных в кавычки значений. Впрочем, не следует забывать, что команды Write-Output, Out-Host и Write-Host в разных обстоятельствах могут вести себя по-разному. Дополнительные сведения об этих командах можно найти в справочных файлах.

Если вы хотите использовать кавычки внутри строки, можете вводить одинарные кавычки внутри двойных или двойные кавычки внутри одинарных:

Write-Output "String 'in' quotes."
Write-Output 'String "in" quotes.'

Вернемся к экрану 1. Обратите внимание, что в обоих случаях в выходных данных отображаются внутренние кавычки. Иные результаты получаются, если в строке используются кавычки только одного типа:

Write-Output "String "in" quotes."
Write-Output 'String 'in' quotes.'

В обоих случаях кавычки не отображаются, и добавляется новая строка. Дело в том, что PowerShell интерпретирует эту одну строку как несколько строк и, соответственно, добавляет символ переноса строки. Так, PowerShell истолковывает String как первую строку (и потому добавляет после нее символ переноса строки), а затем интерпретирует оставшуюся часть текста как отдельную строку. Вы можете использовать двойные кавычки внутри двойных кавычек, но внутренние кавычки при этом придется экранировать (о том, как это делается, я расскажу позже).

Итак, при работе с кавычками всегда будьте внимательны и не путайте тип используемых кавычек (а также не забывайте включать кавычки того или иного типа). Иначе можно оказаться внутри цикла: система предлагает ввести некое значение, но что бы вы ни вводили, цикл не прерывается. Кстати, если вы попадете в такую ситуацию, нажмите сочетание клавиш Ctrl+C, и вы вернетесь к приглашению командной строки.

При определении аргументов команды нужно иметь в виду еще одно обстоятельство, а именно: каким образом оболочка PowerShell трактует численные значения. Как я уже говорил, все заключенные в кавычки значения PowerShell рассматривает как строки — даже если значения состоят из одних только чисел.

Write-Output "123"

Когда выполняется эта инструкция (показанная на экране 2), возвращаемое значение является строковым объектом. Тип этого значения можно проверить, выполнив инструкцию 

(Write-Output "123").GetType ()

В данной инструкции используется метод типа объекта GetType, который в нашем случае является типом String, а точнее — System.String (что тоже показано на экране 2). Дополнительные сведения о System.String и GetType приведены во врезке «Получение и использование членов объектов System.String».

Если численное значение не заключается в кавычки, PowerShell рассматривает его как числовой объект. Так, следующая инструкция возвращает целочисленный объект:

Write-Output 123

И в этом случае тип объекта можно проверить с помощью метода GetType:

(Write-Output 123).GetType ()

Как видно на экране 2, объект принадлежит типу Int32.

Если значение включает в себя как цифры, так и буквы, PowerShell рассматривает его как строку вне зависимости от наличия или отсутствия кавычек. Так, следующая инструкция возвращает строку, что подтверждается при выполнении второй инструкции:

Write-Output 123 output
(Write-Output 123 output).GetType ()

И вновь выходные данные этих инструкций мы можем увидеть на экране 2.

В большинстве случаев кавычки можно опускать, если аргумент представляет собой строку, не содержащую пробелов. В трех следующих инструкциях команда Set-Location используется для того, чтобы указать в качестве рабочей папки накопитель C.

Set-Location C:
Set-Location "C:"
Set-Location ‘C:’

А теперь представим себе, что в качестве рабочей нужно указать новую папку — C:Documents and Settings:

Set-Location `
C:Documents and Settings

Эта инструкция завершается ошибкой, поскольку программа не знает, что делать с маркерами (словами), следующими после первого пробела. Как явствует из экрана 3, анализатор рассматривает слово «and» как параметр, а поскольку параметра с таким именем не существует, анализатор генерирует ошибку. Проблема решается легко — весь аргумент необходимо заключить в кавычки:

Set-Location `
"C:Documents and Settings"

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

Еще один важный вопрос состоит в том, как нужно ссылаться на переменные, которые содержатся в заключенной в кавычки строке. Если строка заключена в двойные кавычки, используется значение переменной. Если же строка заключена в одинарные кавычки, применяется значение литерала. Как я уже отмечал, о переменных, а также о способах ссылки на переменные в строках речь пойдет в следующей статье. Впрочем, если вы хотите уже сейчас получить дополнительную информацию об использовании переменных в строках, обратитесь к справочному файлу about_quoting_rules.

Экранирование специальных символов в строках

В приведенных выше примерах использовались аргументы, которые можно заключать как в одинарные, так и в двойные кавычки. В результате у читателей может сложиться впечатление, будто между двумя типами кавычек нет никаких различий. Однако различие есть, причем весьма важное: одинарные кавычки всегда представляют строку как литерал, тогда как двойные кавычки дают возможность экранировать специальные символы внутри текста. Специальный символ — это такой символ, который, если следует после обратной кавычки (`), предписывает программе предпринять то или иное действие; если же перед специальным символом обратной кавычки нет, упомянутое действие не совершается. В таблице приведен перечень специальных символов оболочки PowerShell.

Эту концепцию удобнее всего осваивать на примерах. В следующих инструкциях ряд символов экранируется с тем, чтобы изменить формат отображения текста.

Write-Output ("`n`tText includes" + ` "`n`t`"escaped`" characters.`n")

Первый экранированный символ (следующий за первой обратной кавычкой) — это литера n; в данном контексте она предписывает вставить новую строку. Второй экранированный символ — t; он вставляет знак табуляции. Отметим, что обратная кавычка в конце первой строки рассматривается не как символ экранирования, а как символ продолжения (см. урок 2). Во второй строке символы `n и `t используются еще несколько раз. Кроме того, обратные кавычки предваряют двойные кавычки, обрамляющие слово escaped. В результате эти двойные кавычки отображаются в выходных данных. Взглянув на экран 4, вы увидите, как отображаются новые строки, знаки табуляции и двойные кавычки. Дополнительные сведения об экранировании символов можно найти в справочном файле about_escape_character.

 

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

Write-Output '`tindented`n`twords'

возвратит строку в точности в той же форме, в какой она была введена (см. экран 4). Отметим, кстати, что в предварительных выпусках PowerShell пользователь мог экранировать символы внутри строк, заключенных в одинарные кавычки, и оболочка корректно анализировала их. Так что вам могут встретиться материалы, в которых утверждается, будто PowerShell именно таким образом обрабатывает строки в одинарных кавычках.

На следующих уроках

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

Роберт Шелдон (contact@rhsheldon.com) — технический консультант и автор большого количества книг по технологиям Microsoft Windows и базам данных


Пoлучение и использование членов объектов System.String

болочка PowerShell рассматривает все строки как объекты System.String. Это значит, что в распоряжение пользователя поступает богатый набор методов и свойств данных объектов. Как было показано в уроке 3, команда Get-Member считывает члены объекта в то время, когда объект передается по конвейеру. Поскольку строка передается в виде объекта, для этой строки можно использовать команду Get-Member. К примеру, следующая инструкция считывает членов объекта для строки test output:

"test output" | Get-Member

Как показано на экране A, строковый объект поддерживает большое число методов, включая Substring и GetType. Если бы мы продолжили просмотр отображенного на экране списка, то обнаружили бы свойство Length, которое отражает число символов в строке.

 

Теперь представим себе, что нам нужно получить дополнительную информацию о методе Substring объекта System.String. Опять-таки мы можем получить нужные сведения с помощью команды Get-Member. Достаточно указать метод Substring в качестве аргумента Get-Member и далее передать полученные результаты по конвейеру команде Format-List

"test output" |
Get-Member Substring |
Format-List

На экране B показан результат выполнения этой инструкции. Обратите внимание на то, что определение включает детали процедуры использования метода. Это синтаксис данного метода. Синтаксис указывает, что при вызове метода мы можем придерживаться одного из двух подходов. Вот они:

System.String Substring (Int32 startIndex)
System.String Substring (Int32 startIndex, Int32 length)

Первый подход предполагает указание пользователем целевой строки и позиции, с которой должна начинаться подстрока. Этот метод возвращает подстроку, которая начинается с указанной позиции и завершается в конце строки. Например, если целевая строка — test output, и нам нужно возвратить подстроку, которая начинается с позиции 5, мы используем инструкцию

("test output").Substring (5)

которая возвратит подстроку output. Как показывает эта инструкция, целевую строку необходимо заключить в скобки, поставить точку, а затем указать имя метода и параметры, опять-таки заключенные в скобки.

При использовании второго подхода пользователь указывает целевую строку, а также стартовую позицию и длину подстроки. Допустим, нам нужно возвратить подстроку, которая начинается в начале строки (позиция 0) и имеет длину в четыре символа. Итак, создаем инструкцию

("test output").Substring (0,4)

и она возвращает нам подстроку test.

Когда пользователь вызывает метод, например, Substring или GetType, этот метод создает собственный объект, который может быть передан по конвейеру. В результате пользователь может с помощью команды Get-Member получать список этих членов объекта. К примеру, метод GetType возвращает объект System.RuntimeType, а этот объект поддерживает многочисленные методы и свойства. Следующая инструкция возвращает список свойств, которыми располагает объект System.RuntimeType:

("test output").GetType () |
Get-Member -MemberType Property

Как показывает инструкция, сначала нужно заключить строку в скобки, добавить точку и затем ввести имя метода — в данном случае это GetType. Затем объект, возвращаемый методом GetType, передается по конвейеру команде Get-Member. Обратите внимание: я использовал параметр MemberType для того, чтобы отобразить только возвращенные параметры объекта. Результаты представлены на экране С.