Они используют много старых ярлыков, которые большинство людей больше не использовать. Вот код снова с отсутствующей переменной по умолчанию. Я также перевернул инструкцию unless
в более стандартный формат. То есть, я сделал ему if
заявление и поставить next
как часть if
блока:
while ($_ = <>) {
if (not $_ =~ s/^(.*?):\s*//) {
next;
}
$HoA{$1} = [ split(/\s+/, $_) ];
}
Таким образом, мы устанавливаем значение $_
из diamond operator. Это в основном принимает имена файлов в командной строке и читает каждую строку в этих файлах. Если в командной строке нет файлов, они читаются из STDIN.
Регулярное выражение сложнее. ^
привязывает регулярное выражение к началу строки. В противном случае регулярное выражение может появляться в любом месте строки. Например:
/FOO/ #Will match "FOOBAR" "BARFOOBAR", or "BARFOO"
/^FOO/ #Will only match "FOOBAR" and not "BARFOOBAR" or "BARFOO"
.
означает любой символ. Значение *
означает ноль или более предыдущего. Таким образом, .*
означает любое количество символов (включая нулевые символы.Например:
/^.*:/ #Will match any combination of characters followed by a colon (:).
Таким образом, этот матч будет :
на линии все само по себе (ноль или более), или this is a test:
Сложная часть является ?
, который изменяет значение *
в очень тонким способом. Обычно регулярные выражения жадные. Они пытаются соответствовать самому большому матчу они могут, так что если у вас есть строка:
my $string = "abc:def:ghij";
$string =~ /^.*:/;
Регулярное выражение будет соответствовать самой большой вещи она может. Таким образом, вышесказанное соответствует abc:def:
, так как это самая длинная строка, заканчивающаяся двоеточием. Поместив ?
после *
, вы делаете регулярное выражение как не-жадным - то есть оно будет соответствовать наименьшему возможному выражению. Таким образом:
my $string = "abc:def:ghij";
$string =~ /^(.*):/ #Matches "abc:def:
$string =~ /^(.*?):/ #Matches "abc:"
\s
означает любое пустое пространство, которое, как правило, означает быть пробел или символ табуляции. *
означает ноль или более этих пространств. Таким образом, это может быть не пробел или несколько пробелов.
my $string = "abc:def: foo";
$string =~ /^(.*?):\s*/; #Matches "abc:"
$string = "abc: This is a test";
$string =~ /^(.*?):\s*/; #Matches "abc: "
Теперь s
перед регулярным выражением означает замену. Основной формат:
$string =~ s/regex/string/;
Где regex
регулярное выражение, которое соответствует что-то в то время как $string
string
является замена в матче. Простым примером является:
$string = "My name is David";
$string =~ s/David/Bill/; #String is now "My name is Bill"
В этом случае символы, соответствующие регулярному выражению, просто заменяются ничем. То есть, они удаляются из строки:
$string = "abc: def";
$string =~ /^(.*?):\s*/; #$string is now "def". "abc: " has been removed
Итак, еще один взгляд на ваш код:
while ($_ = <>) {
if (not $_ =~ s/^(.*?):\s*//) {
next;
}
$HoA{$1} = [ split(/\s+/, $_) ];
}
Это чтение из файлов, перечисленных в командной строке, или из STDIN, и ищет строки, содержащие двоеточие. Если строка не содержит двоеточие, она читает следующую строку.
Если строка содержит двоеточие, первая часть строки до начинается с двоеточия и любые последующие пробелы удаляются из строки.
$1
относится к той части строки, которая была сопоставлена в круглых скобках в предыдущем регулярном выражении. Это первая часть строки до первого двоеточия. split
разделяет оставшуюся часть строки, разделенную пробелами, и превращает ее в так называемый анонимный список . То есть, это создает хэш массивов (поэтому этот хэш называется HoA (Hash of Arrays).
Давайте приведем несколько примеров строк:
____________________________________________________
| STRING | RESULTS |
|_________________|________________________________|
| abc: foobar | $HoA{abc} = ["foobar"] |
| def:bar fu | $HoA{def} = ["bar", "fu"] |
| ghi:jkl:mno | $HoA{ghi} = ["jkl:mno"] |
| ghi : jkl: mn: | $HoA{"ghi "} = ["jkl:", "mn:"] |
|_________________|________________________________|
Обратите внимание, что последний будет иметь место в конце ключа. Это «ghi», а не «ghi».
На самом деле нет ничего старого или неиспользованного использования '$ _' неявно, пока оно находится в небольшой области (две строки кажутся прекрасными). В этом случае это не так много. 'if' и неявные переменные являются частью языка; при их использовании они являются мощными и понятными; не записывайте их так быстро. Кроме того, используя 'split', как это, вы просто хотите проверить [' perldoc -f split'] (http://p3rl.org/split), чтобы узнать, что он делает! –
p.s. не уменьшилось, время выглядит плохо, хотя –
@JoelBerger - Вы правы, что предполагаемое использование '$ _' в этом конкретном случае не ухудшает читаемость, но оно действительно не улучшает его. Программирование - это 10% -ное кодирование и 90% обслуживание, а '$ _' просто делает эту 90% -ную часть сложнее, поэтому ее не поощряют. У вас нет полного контроля над '$ _', поэтому он может измениться без вашего ведома. Конвей не поощрял использование _post-fixed_ 'if' и использование' except' вместо 'if'. Тем не менее, он, вероятно, одобрил бы пост, зафиксированный «если» в этом конкретном случае. –