Символ табуляции имеет длинную историю. Впервые табуляция появилась у пишущих машинок, она позволяла задавать переход каретки на одну или несколько позиций. При нажатии на клавишу Tab каретка перемещалась на следующую позицию. На компьютере табуляция имеет ASCII-код 9. На дисплее телетайпа (например, на терминале UNIX или в консольной программе Windows) при нажатии табуляции курсор перемещается в ближайший справа столбец с номером, кратным 8 (отсчет начинается в столбце 0). Например, если курсор находится в любом из столбцов от 0 до 7, то при нажатии на табуляцию он переместится в столбец 8 (то есть в девятый столбец, поскольку счет ведется от 0).

На компьютере табуляция применяется и в других случаях. Например, различные средства управления базами данных и электронными таблицами позволяют выводить данные в формате с разделителями значений символом табуляции (TSV). .

Во избежание путаницы часто бывает полезно «детабулировать» содержимое файла, то есть заменить табуляцию на нужное число пробелов. Это применимо к текстовым файлам, где символы табуляции используются для отступов – например, к сценариям, файлам XML и HTML. В Windows есть команда more.com, которая позволяет заменять табуляцию на пробелы, но я для выполнения этой задачи создал собственную функцию PowerShell.

Функция Expand-Tab

Функция Expand-Tab приведена в листинге 1.

К каждой вводимой строке применяется обработка, описываемая регулярным выражением. В результате выдается строка, в которой символы табуляции заменены соответствующим числом пробелов. Число пробелов для отступа можно указать (по умолчанию – 8). Для полного удаления символов табуляции укажите 0.

Манипуляции, выполняемые с входной строкой, описаны в блоке сценария process. Сначала входной строке (то есть $_) назначается переменная $line. Затем выполняется цикл while, который повторяется, пока во входной строке есть символы табуляции. Переменная $i хранит позицию в строке, где встречается символ табуляции. Если $i – -1 (то есть символа табуляции нет), то осуществляется выход из цикла while по инструкции break.

Затем ширина отступа ($TabWidth) сравнивается с 0. Если $TabWidth > 0, то с помощью оператора * создается строка $pad, состоящая из нужного числа пробелов. В PowerShell запись строка * n означает «строка, повторенная n раз», поэтому $pad будет состоять из $TabWidth — ($i % $TabWidth) пробелов. Если $TabWidth = 0, то в качестве $pad выводится пустая строка.

Наконец, применяется оператор –replace с регулярным выражением для вывода копии строки $line, в которой символы табуляции заменены строкой $pad (то есть вычисленным количеством пробелов). В приведенной таблице описаны компоненты регулярного выражения.

 

Компоненты регулярного выражения

Применение функции Expand-Tab

Я поместил функцию Expand-Tab в свой модуль PowerShell, и она всегда под рукой. Вот пример ее применения:

Get-Content t1.ps1 | Expand-Tab | Out-File t2.ps1

В этой команде берется содержимое файла t1.ps1, каждый символ табуляции заменяется до восьми пробелов, и «детабулированное» содержимое сохраняется в файл t2.ps1. Если ширина отступа в восемь пробелов, принятая по умолчанию, слишком велика, то можно указать другое значение. В частности, в приведенной ниже команде указано два пробела:

Get-Content t1.txt | Expand-Tab 2 | Out-File t2.txt

Заметим, что указывать имя параметра –TabWidth не нужно, так как PowerShell знает, что TabWidth – это первый параметр функции.

Управляйте табуляцией

Если вы добавите функцию Expand-Tab в свой модуль PowerShell, вам не придется больше беспокоиться о том, что содержат текстовые файлы – пробелы или табуляцию.

Листинг 1. Функция Expand-Tab

function Expand-Tab {
param([UInt32] $TabWidth = 8)
process {
$line = $_
while ( $TRUE ) {
$i = $line.IndexOf([Char] 9)
if ( $i -eq -1 ) { break }
if ( $TabWidth -gt 0 ) {
$pad = «" * ($TabWidth — ($i % $TabWidth))
} else {
$pad =»«
}
$line = $line -replace»^([^t]{$i})t(.*)$«,
»`$1$pad`$2"
}
$line
}
}