Анимация
JavaScript
|
Главная Библионтека 1.8. Расширение переменных во входных данных 41 Загадочная конструкция 1 while CONDITION эквивалентна while (CONDITION) {}, но более компактна. Она появилась в те дни, когда первая конструкция работала в Perl несравнимо быстрее второй. Хотя сейчас второй вариант почти не уступает по скорости, первый стал удобным и привычным. Стандартный модуль Text::Tabs содержит функции преобразований в обоих направлениях, экспортирует переменную $tabstop, которая определяет число пробелов на символ табуляции. Кроме того, это не приводит к снижению быстродействия, потому что вместо $& и $ используются $1 и $2: use Text Tabs, Stabstop = 4, while (<>) { print expand($ ) } Модуль Text:;Tabs также может применяться для «сжатия» табуляции. В следующем примере используется стандартное значение Stabstop, равное 8; use Text Tabs, while (О) { print unexpand($ ) } > Смотри также- Страница руководства модуля Text::Tabs; описание оператора s / врег1ге{\) и рег1ор{\). 1.8. Расширение переменных во входных данных Проблема Имеется строка, внутри которой присутствует ссылка на переменную: You owe $debt to me Требуется заменить имя переменной $debt в строке ее текущим значением. Решение Если все переменные являются глобальными, воспользуйтесь подстановкой с символическими ссылками: $text =~s/\$(\w+)/${$i;/g. Но если среди переменных могут встречаться лексические (ту) переменные, следует использовать /ее: $text = s/(\$\w+)/$1/gee. Комментарий Первый способ фактически сводится к следующему: мы ищем нечто похожее на имя переменной, а затем интерполируем ее значение посредством символического разыменования (dereferencing). Если $1 содержит строку somevar, то ${$1} будет равно содержимому Ssomevar. Такой вариант не будет работать при действую- щей директиве use st not ref s, потому что она запрещает символическое разыменование. Приведем пример: use vars qw($rows $cols); no strict refs, tt для приведенного ниже ${$1} my $text; ($rows, Scols) = (24, 80); $text = q(I am $ rows high and $cols long); # апострофы $text =- s/\$(\w+)/${$1}/g; print $text, 1 am 24 high and 80 long Возможно, вам уже приходилось видеть, как модификатор подстановки /е используется для вычисления заменяющего выражения, а не строки. Допустим, вам потребовалось удвоить каждое целое число в строке: $text = I am 17 years old ; $text = s/(\d+)/2 * $1/eg; Перед запуском программы, встречая /е при подстановке, Perl компилирует код заменяющего выражения вместе с остальной программой, задолго до фактической подстановки. При выполнении подстановки $1 заменяется найденной строкой. В нашем примере будет вычислено следующее выражение: 2 • 17 Но если попытаться выполнить следующий фрагмент: $text = 1 am $AGE years old; # Обратите внимание на апострофы $text =- s/(\$\w+)/$1/eg; п НЕВЕРНО При условии, что $text содержит и.мя переменной $AGE, Perl послушно заменит $1 на SAGE и вычислит следующее выражение: $AGE В результате мы возвращаемся к исходной строке. Чтобы получить значение переменной, необходимо снова вычислить результат. Для этого в строку добавляется еще один модификатор /е: $text =~ s/(\$\w+)/$1/eeg; П Находит переменные ту() Да, количество модификаторов /е может быть любым. Только первый модификатор компилируется вместе с программой и проверяется на правильность синтаксиса. В результате он работает аналогично конструкции eval {BLOCK}, хотя и не перехватывает исключений. Возможно, лучше провести аналогию с do {BLOCK}. Остальные модификаторы /е ведут себя иначе и больше напоминают конструкцию eval "STRING ". Они не компилируются до выполнения программы. Маленькое преимущество этой схемы заключается в том, что вам не придется вставлять в блок директиву по strict refs. Есть и другое огромное преимущество: этот 1.9. Преобразование регистра 43 механизм позволяет находить лексические переменные, созданные с помощью ту, - символическое разыменование на это не способно. В следующем примере модификатор /х разрешает пропуски и комментарии в шаблоне подстановки, а модификатор /е вычисляет правостороннее выражение на программном уровне. Модификатор /е позволяет лучше управлять обработкой ошибок или других экстренных ситуаций: й Расширить переменные в $text Если переменная не определена, # вставить сообщение об ошибке. $text =~ s{ \$ # Найти знак доллара (\w+) # Найти "слово и сохранить его в $1 по strict refs; if (defined $$1) { $$1; # Расширять только глобальные переменные } else { "[N0 VARIABLE- \$$1]; # Сообщение об ошибке }едх; Обратите внимание на изменение синтаксиса $$1 в Perl 5.004; когда-то это выражение означало ${$}1, а теперь оно означает ${$1}. Для обеспечения обратной совместимости в строках оно сохраняет старый смысл (но выдает предупреждение с -w). Запись ${$1} используется в строках для того, чтобы предотвратить разыменование PID. Если значение $$ равно 23448, то $$1 в строке превращается в 234481, а не в значение переменной, имя которой хранится в $1. > Смотри также- Описание оператора s / в perlre(l) и perlop{l); описание функции eval в perlfunc(\). Аналогичное использование подстановок встречается в рецепте 20.9. 1.9. Преобразование регистра Проблема Строку с символами верхнего регистра необходимо преобразовать в нижний регистр, или наоборот. Решение Воспользуйтесь функциями 1с и ис со служебными командами \L и \U: use locale; # Необходимо в 5.004 и выше $big = uc($little); П "bo peep" -> "ВО PEEP" Slittle = lc($big); # "JOHN -> "john" 0 1 2 3 4 5 6 7 [ 8 ] 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |