Я отвечу серьезно. Я не знаю ни одной программы для перевода сценария оболочки в Perl, и я сомневаюсь, что какой-либо модуль интерпретатора обеспечит выигрыш в производительности. Поэтому я дам краткое описание того, как бы я поступил по этому поводу.
Теперь вы хотите максимально использовать свой код. В этом случае я предлагаю выбрать фрагменты этого кода, написать его версию Perl и затем вызвать скрипт Perl из основного скрипта. Это позволит вам выполнять преобразование небольшими шагами, утверждать, что преобразованная часть работает, и постепенно улучшать свои знания Perl.
Поскольку вы можете вызывать внешние программы из сценария Perl, вы даже можете заменить какую-то большую логику на Perl и вызывать меньшие сценарии оболочки (или другие команды) из Perl, чтобы сделать что-то, что вам пока не очень удобно конвертировать. Таким образом, у вас будет сценарий оболочки, вызывающий сценарий Perl, вызывающий другой сценарий оболочки. И, собственно, я сделал именно это с помощью своего самого первого скрипта Perl.
Конечно, важно хорошо выбрать, что конвертировать. Ниже я объясню, сколько шаблонов, распространенных в сценариях оболочки, написано на Perl, чтобы вы могли идентифицировать их внутри своего сценария и создавать замены с максимально возможным количеством операций вырезания и вставки.
Во-первых, и сценарии Perl, и сценарии оболочки - это код + функции. То есть все, что не является объявлением функции, выполняется в том порядке, в котором оно встречается. Вам не нужно объявлять функции перед использованием, хотя. Это означает, что общий макет сценария может быть сохранен, хотя способность хранить вещи в памяти (например, целый файл или его обработанную форму) позволяет упростить задачи.
Скрипт Perl в Unix начинается примерно так:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
#other libraries
(rest of the code)
Первая строка, очевидно, указывает на команды, которые будут использоваться для запуска скрипта, как это делают обычные оболочки. Следующие две строки «использования» делают язык более строгим, что должно уменьшить количество ошибок, с которыми вы сталкиваетесь, потому что вы плохо знаете язык (или просто что-то не так). Третья строка использования импортирует функцию «Dumper» модуля «Данные». Это полезно для отладки. Если вы хотите узнать значение массива или хеш-таблицы, просто выведите Dumper (что угодно).
Обратите внимание, что комментарии похожи на оболочки, строки начинаются с "#".
Теперь вы вызываете внешние программы и передаете или отправляете из них. Например:
open THIS, "cat $ARGV[0] |";
Это будет запускать cat, передавая "$ARGV[0]
", что будет $ 1 на оболочке - первый передаваемый ей аргумент. Результат этого будет передан в ваш Perl-скрипт через «ЭТО», который вы можете использовать, чтобы прочитать это из него, как я покажу позже.
Вы можете использовать "|" в начале или в конце строки, чтобы указать режим «pipe to» или «pipe from» и указать команду, которую нужно выполнить, и вы также можете использовать «>» или «>>» в начале, чтобы открыть файл для записи с усечением или без него, «<» для явного указания открытия файла для чтения (по умолчанию) или «+ <» и «+>» для чтения и записи. Обратите внимание, что последний сначала урежет файл.
Другой синтаксис «open», который позволит избежать проблем с файлами с такими символами в именах, имеет режим открытия в качестве второго аргумента:
open THIS, "-|", "cat $ARGV[0]";
Это будет делать то же самое. Режим "- |" обозначает «труба из», а «| -» обозначает «труба из». Остальные режимы можно использовать как есть (>, >>, <, +>, +<
). Несмотря на то, что нужно открыть больше, этого должно хватить для большинства вещей.
Но вам следует избегать вызова внешних программ в максимально возможной степени. Вы можете открыть файл напрямую, например, с помощью open THIS, "$ARGV[0]";
и получить гораздо лучшую производительность.
Итак, какие внешние программы вы могли бы вырезать? Ну, почти все. Но давайте останемся с основами: кошка, grep, вырезать, голова, хвост, uniq, wc, sort.
CAT
Ну, об этом особо нечего сказать. Просто помните, что, если возможно, прочитайте файл только один раз и сохраните его в памяти. Если файл огромен, вы, конечно, этого не сделаете, но почти всегда есть способы избежать чтения файла более одного раза.
В любом случае, основной синтаксис для cat будет:
my $filename = "whatever";
open FILE, "$filename" or die "Could not open $filename!\n";
while(<FILE>) {
print $_;
}
close FILE;
При этом открывается файл и печатается все его содержимое («while(<FILE>)
» будет зацикливаться до EOF, присваивая каждой строке «$_
») и снова его закрывает.
Если бы я хотел перенаправить вывод в другой файл, я мог бы сделать это:
my $filename = "whatever";
my $anotherfile = "another";
open (FILE, "$filename") || die "Could not open $filename!\n";
open OUT, ">", "$anotherfile" or die "Could not open $anotherfile for writing!\n";
while(<FILE>) {
print OUT $_;
}
close FILE;
Будет напечатана строка в файл, обозначенный "OUT
". Вы также можете использовать STDIN
, STDOUT
и STDERR
в соответствующих местах, не открывая их в первую очередь. На самом деле, print
по умолчанию STDOUT
, а die
по умолчанию STDERR
.
Обратите внимание также на "or die ...
" и "|| die ...
". Операторы or
и ||
означают, что следующая команда будет выполняться только в том случае, если первая возвращает ложь (что означает пустую строку, нулевую ссылку, 0 и т. П.). Команда die останавливает скрипт с сообщением об ошибке.
Основное различие между "or
" и "||
" является приоритетным. Если в приведенных выше примерах «or
» был заменен на «||
», он не будет работать должным образом, поскольку строка будет интерпретироваться как:
open FILE, ("$filename" || die "Could not open $filename!\n");
Что совсем не то, что ожидается. Так как «or
» имеет более низкий приоритет, он работает. В строке, где используется "||
", параметры open
передаются в скобках, что позволяет использовать "||
".
Увы, есть кое-что, что в значительной степени делает то, что делает кошка:
while(<>) {
print $_;
}
Это будет печатать все файлы в командной строке, или что-нибудь переданное через STDIN.
GREP
Итак, как будет работать наш скрипт "grep"? Я приму «grep -E», потому что в Perl это проще, чем в простом grep. В любом случае:
my $pattern = $ARGV[0];
shift @ARGV;
while(<>) {
print $_ if /$pattern/o;
}
"o", передаваемое в $ patttern, указывает Perl компилировать этот шаблон только один раз, тем самым увеличивая вашу скорость. Не стиль "что-то, если cond". Это означает, что он выполнит «что-то», только если условие истинно. Наконец, «/$pattern/
», само по себе, совпадает с «$_ =~ m/$pattern/
», что означает сравнение $ _ с указанным шаблоном регулярных выражений. Если вы хотите стандартное поведение grep
, то есть просто сопоставление подстрок, вы можете написать:
print $_ if $_ =~ "$pattern";
CUT
Обычно лучше использовать группы регулярных выражений, чтобы получить точную строку, чем cut. Что бы вы сделали с «седом», например. В любом случае, есть два способа воспроизведения вырезки:
while(<>) {
my @array = split ",";
print $array[3], "\n";
}
Это даст вам четвертый столбец каждой строки, используя "," в качестве разделителя. Примечание @array
и $array[3]
. Символ @
означает, что «массив» следует рассматривать как массив. Он получит массив, состоящий из каждого столбца в текущей обработанной строке. Далее, символ $
означает, что array[3]
является скалярным значением. Он вернет столбец , который вы запрашиваете.
Это не очень хорошая реализация, так как «split» будет сканировать всю строку. Однажды я сократил процесс с 30 минут до 2 секунд, просто не используя разбиение - хотя строки были довольно большими. В любом случае, следующее имеет превосходную производительность, если ожидается, что строки будут большими, а столбцы - низкими:
while(<>) {
my ($column) = /^(?:[^,]*,){3}([^,]*),/;
print $column, "\n";
}
Это использует регулярные выражения для получения нужной информации, и только это.
Если вы хотите позиционные столбцы, вы можете использовать:
while(<>) {
print substr($_, 5, 10), "\n";
}
, который будет печатать 10 символов, начиная с шестого (опять же, 0 означает первый символ).
ГОЛОВА
Это довольно просто:
my $printlines = abs(shift);
my $lines = 0;
my $current;
while(<>) {
if($ARGV ne $current) {
$lines = 0;
$current = $ARGV;
}
print "$_" if $lines < $printlines;
$lines++;
}
Здесь стоит отметить. Я использую "ne" для сравнения строк. Теперь $ ARGV всегда будет указывать на текущий файл для чтения, поэтому я отслеживаю их, чтобы возобновить мой подсчет, когда я читаю новый файл. Также обратите внимание на более традиционный синтаксис «если», прямо после постфиксного.
Я также использую упрощенный синтаксис, чтобы получить количество строк для печати. Когда вы используете «shift» само по себе, оно предполагает «shift @ARGV». Также обратите внимание, что shift, помимо изменения @ARGV, вернет элемент, который был из нее смещен.
Как и в случае с оболочкой, нет различия между числом и строкой - вы просто используете это. Даже такие вещи, как "2" + "2" будут работать. На самом деле, Perl еще более снисходительный, с радостью рассматривая все, что не является числом, как 0, так что вы можете быть осторожны.
Этот скрипт очень неэффективен, так как он читает ВСЕ файл, а не только необходимые строки. Давайте улучшим его и увидим пару важных ключевых слов в процессе:
my $printlines = abs(shift);
my @files;
if(scalar(@ARGV) == 0) {
@files = ("-");
} else {
@files = @ARGV;
}
for my $file (@files) {
next unless -f $file && -r $file;
open FILE, "<", $file or next;
my $lines = 0;
while(<FILE>) {
last if $lines == $printlines;
print "$_";
$lines++;
}
close FILE;
}
Ключевые слова "следующий" и "последний" очень полезны. Сначала «next» скажет Perl вернуться к условию цикла, получив следующий элемент, если это применимо. Здесь мы используем его, чтобы пропустить файл, если он действительно не является файлом (не каталогом) и доступен для чтения. Он также будет пропущен, если мы не сможем открыть файл даже тогда.
Тогда «последний» используется, чтобы немедленно выпрыгнуть из цикла. Мы используем его, чтобы прекратить чтение файла, как только мы достигли необходимого количества строк. Это правда, что мы читаем одну строку слишком много, но наличие «последней» в этой позиции ясно показывает, что строки после нее не будут выполнены.
Существует также «повторить», которая вернется к началу цикла, но без переоценки условия и получения следующего элемента.
TAIL
Я сделаю небольшой трюк здесь.
my $skiplines = abs(shift);
my @lines;
my $current = "";
while(<>) {
if($ARGV ne $current) {
print @lines;
undef @lines;
$current = $ARGV;
}
push @lines, $_;
shift @lines if $#lines == $skiplines;
}
print @lines;
Хорошо, я комбинирую «push», который добавляет значение к массиву, со «shift», который берет что-то из начала массива. Если вам нужен стек, вы можете использовать push / pop или shift / unshift. Смешайте их, и у вас есть очередь. Я сохраняю свою очередь максимум с 10 элементами с $#lines
, что даст мне индекс последнего элемента в массиве. Вы также можете получить количество элементов в @lines
с помощью scalar(@lines)
.
UNIQ
Теперь uniq удаляет только повторяющиеся последовательные строки, что должно быть легко с тем, что вы видели до сих пор. Поэтому я устраню их все:
my $current = "";
my %lines;
while(<>) {
if($ARGV ne $current) {
undef %lines;
$current = $ARGV;
}
print $_ unless defined($lines{$_});
$lines{$_} = "";
}
Теперь я храню весь файл в памяти, внутри %lines
. Использование символа %
указывает, что это хеш-таблица. Я использую строки в качестве ключей и ничего не храню в качестве значений - так как меня не интересуют значения. Я проверяю, где существует ключ, с помощью «определено ($ lines {$ _})», которое проверит, определено ли значение, связанное с этим ключом; ключевое слово "never" работает так же, как "if", но с противоположным эффектом, поэтому оно печатает строку, только если строка НЕ определена.
Также обратите внимание на синтаксис $lines{$_} = ""
как способ хранения чего-либо в хеш-таблице. Обратите внимание на использование {}
для хеш-таблицы, в отличие от []
для массивов.
WC
Это на самом деле будет использовать много вещей, которые мы видели:
my $current;
my %lines;
my %words;
my %chars;
while(<>) {
$lines{"$ARGV"}++;
$chars{"$ARGV"} += length($_);
$words{"$ARGV"} += scalar(grep {$_ ne ""} split /\s/);
}
for my $file (keys %lines) {
print "$lines{$file} $words{$file} $chars{$file} $file\n";
}
Три новые вещи. Два - оператор «+ =», который должен быть очевидным, и выражение «для». По сути, «for» назначит каждый элемент массива указанной переменной. «My» существует для объявления переменной, хотя она и не требуется, если объявлена ранее. Я мог бы иметь переменную @array внутри этих скобок. Выражение «keys% lines» будет возвращено в виде массива ключей (имен файлов), которые существуют для хеш-таблицы «% lines». Остальное должно быть очевидным.
Третье, что я на самом деле добавил, только пересматривая ответ, - это "grep". Формат здесь:
grep { code } array
Он будет запускать «код» для каждого элемента массива, передавая элемент как «$ _». Затем grep вернет все элементы, для которых код оценивается как «true» (не 0, не «» и т. Д.). Это позволяет избежать подсчета пустых строк, полученных из последовательных пробелов.
Подобно "grep", есть "карта", которую я не буду здесь демонстрировать. Вместо фильтрации он вернет массив, сформированный по результатам «кода» для каждого элемента.
СНП
Наконец, сортировка. Это тоже легко:
my @lines;
my $current = "";
while(<>) {
if($ARGV ne $current) {
print sort @lines;
undef @lines;
$current = $ARGV;
}
push @lines, $_;
}
print sort @lines;
Здесь "sort" будет сортировать массив. Обратите внимание, что sort может получить функцию для определения критериев сортировки. Например, если бы я хотел отсортировать числа, я мог бы сделать это:
my @lines;
my $current = "";
while(<>) {
if($ARGV ne $current) {
print sort @lines;
undef @lines;
$current = $ARGV;
}
push @lines, $_;
}
print sort {$a <=> $b} @lines;
Здесь "$a
" и "$b
" получают элементы для сравнения. «<=>
» возвращает -1, 0 или 1 в зависимости от того, меньше ли число, равно или больше другого. Для строк "cmp" делает то же самое.
ОБРАЩЕНИЕ С ФАЙЛАМИ, СПРАВОЧНИКАМИ И ДРУГИМИ ПЕРСОНАЛАМИ
В остальном основные математические выражения должны быть просты для понимания. Вы можете проверить определенные условия для файлов следующим образом:
for my $file (@ARGV) {
print "$file is a file\n" if -f "$file";
print "$file is a directory\n" if -d "$file";
print "I can read $file\n" if -r "$file";
print "I can write to $file\n" if -w "$file";
}
Я не пытаюсь быть исчерпывающим, есть много других подобных тестов. Я также могу сделать шаблоны "glob", такие как "*" и "?", Например:
for my $file (glob("*")) {
print $file;
print "*" if -x "$file" && ! -d "$file";
print "/" if -d "$file";
print "\t";
}
Если вы объединили это с "chdir", вы также можете эмулировать "find":
sub list_dir($$) {
my ($dir, $prefix) = @_;
my $newprefix = $prefix;
if ($prefix eq "") {
$newprefix = $dir;
} else {
$newprefix .= "/$dir";
}
chdir $dir;
for my $file (glob("*")) {
print "$prefix/" if $prefix ne "";
print "$dir/$file\n";
list_dir($file, $newprefix) if -d "$file";
}
chdir "..";
}
list_dir(".", "");
Здесь мы видим, наконец, функцию. Функция объявлена с синтаксисом:
sub name (params) { code }
Строго говоря, "(params)" необязательно. Объявленный параметр, который я использовал, «($$)
», означает, что я получаю два скалярных параметра. Я мог бы также иметь "@
" или "%
". Массив "@_
" имеет все переданные параметры. Строка "my ($dir, $prefix) = @_
" - это простой способ присвоения первых двух элементов этого массива переменным $dir
и $prefix
.
.
Эта функция ничего не возвращает (на самом деле это процедура), но вы можете иметь функции, которые возвращают значения, просто добавив к ней «return something;
» и сделав так, чтобы она возвращала «что-то».
Остальное должно быть довольно очевидно.
СМЕШИВАНИЕ ВСЕГО
Теперь я приведу более сложный пример. Я покажу плохой код, чтобы объяснить, что с ним не так, а затем покажу лучший код.
Для этого первого примера у меня есть два файла, файл names.txt, в котором указаны имена и номера телефонов, systems.txt, с системами и именем ответственного за них. Вот они:
names.txt
John Doe, (555) 1234-4321
Jane Doe, (555) 5555-5555
The Boss, (666) 5555-5555
systems.txt
Sales, Jane Doe
Inventory, John Doe
Payment, That Guy
Затем я хочу напечатать первый файл с системой, добавленной к имени человека, если этот человек отвечает за эту систему. Первая версия может выглядеть так:
#!/usr/bin/perl
use strict;
use warnings;
open FILE, "names.txt";
while(<FILE>) {
my ($name) = /^([^,]*),/;
my $system = get_system($name);
print $_ . ", $system\n";
}
close FILE;
sub get_system($) {
my ($name) = @_;
my $system = "";
open FILE, "systems.txt";
while(<FILE>) {
next unless /$name/o;
($system) = /([^,]*)/;
}
close FILE;
return $system;
}
Однако этот код не будет работать. Perl будет жаловаться, что функция использовалась слишком рано для проверки прототипа, но это всего лишь предупреждение. Это выдаст ошибку в строке 8 (первый цикл while), что приведет к появлению строки чтения в закрытом дескрипторе файла. Здесь произошло то, что «FILE
» является глобальным, поэтому функция get_system
меняет его. Давайте перепишем это, исправив обе вещи:
#!/usr/bin/perl
use strict;
use warnings;
sub get_system($) {
my ($name) = @_;
my $system = "";
open my $filehandle, "systems.txt";
while(<$filehandle>) {
next unless /$name/o;
($system) = /([^,]*)/;
}
close $filehandle;
return $system;
}
open FILE, "names.txt";
while(<FILE>) {
my ($name) = /^([^,]*),/;
my $system = get_system($name);
print $_ . ", $system\n";
}
close FILE;
Это не даст никакой ошибки или предупреждения, и не будет работать. Он возвращает только системы, но не имена и номера телефонов! Что случилось? Что ж, произошло то, что мы делаем ссылку на "$_
" после вызова get_system
, но, читая файл, get_system
перезаписывает значение $_
!
Чтобы избежать этого, мы сделаем $_
локальным внутри get_system
. Это придаст ему локальную область видимости, и исходное значение будет затем восстановлено после возврата из get_system
:
#!/usr/bin/perl
use strict;
use warnings;
sub get_system($) {
my ($name) = @_;
my $system = "";
local $_;
open my $filehandle, "systems.txt";
while(<$filehandle>) {
next unless /$name/o;
($system) = /([^,]*)/;
}
close $filehandle;
return $system;
}
open FILE, "names.txt";
while(<FILE>) {
my ($name) = /^([^,]*),/;
my $system = get_system($name);
print $_ . ", $system\n";
}
close FILE;
И это все еще не работает! Он печатает новую строку между именем и системой. Ну, Perl читает строку, включая любую новую строку, которая может быть. Есть аккуратная команда, которая удалит новые строки из строк, "chomp
", которую мы будем использовать для решения этой проблемы. И поскольку не у каждого имени есть система, мы можем также избежать печати запятой, когда это произойдет:
#!/usr/bin/perl
use strict;
use warnings;
sub get_system($) {
my ($name) = @_;
my $system = "";
local $_;
open my $filehandle, "systems.txt";
while(<$filehandle>) {
next unless /$name/o;
($system) = /([^,]*)/;
}
close $filehandle;
return $system;
}
open FILE, "names.txt";
while(<FILE>) {
my ($name) = /^([^,]*),/;
my $system = get_system($name);
chomp;
print $_;
print ", $system" if $system ne "";
print "\n";
}
close FILE;
Это работает, но также оказывается ужасно неэффективным. Мы читаем весь системный файл для каждой строки в файле имен. Чтобы избежать этого, мы будем читать все данные из систем один раз, а затем использовать их для обработки имен.
Теперь, иногда файл настолько велик, что вы не можете прочитать его в память. Когда это происходит, вы должны попытаться прочитать в память любой другой файл, необходимый для его обработки, чтобы вы могли сделать все за один проход для каждого файла. В любом случае, вот первая оптимизированная версия:
#!/usr/bin/perl
use strict;
use warnings;
our %systems;
open SYSTEMS, "systems.txt";
while(<SYSTEMS>) {
my ($system, $name) = /([^,]*),(.*)/;
$systems{$name} = $system;
}
close SYSTEMS;
open NAMES, "names.txt";
while(<NAMES>) {
my ($name) = /^([^,]*),/;
chomp;
print $_;
print ", $systems{$name}" if defined $systems{$name};
print "\n";
}
close NAMES;
К сожалению, это не работает. Ни одна система не появляется! Что произошло? Что ж, давайте посмотрим, что содержит "%systems
", используя Data::Dumper
:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
our %systems;
open SYSTEMS, "systems.txt";
while(<SYSTEMS>) {
my ($system, $name) = /([^,]*),(.*)/;
$systems{$name} = $system;
}
close SYSTEMS;
print Dumper(%systems);
open NAMES, "names.txt";
while(<NAMES>) {
my ($name) = /^([^,]*),/;
chomp;
print $_;
print ", $systems{$name}" if defined $systems{$name};
print "\n";
}
close NAMES;
Вывод будет примерно таким:
$VAR1 = ' Jane Doe';
$VAR2 = 'Sales';
$VAR3 = ' That Guy';
$VAR4 = 'Payment';
$VAR5 = ' John Doe';
$VAR6 = 'Inventory';
John Doe, (555) 1234-4321
Jane Doe, (555) 5555-5555
The Boss, (666) 5555-5555
Эти $VAR1/$VAR2/etc
- это то, как Dumper
отображает хеш-таблицу. Нечетные числа - это ключи, а последующие четные числа - это значения. Теперь мы видим, что у каждого имени в %systems
есть предшествующий пробел! Глупая ошибка регулярного выражения, давайте исправим это:
#!/usr/bin/perl
use strict;
use warnings;
our %systems;
open SYSTEMS, "systems.txt";
while(<SYSTEMS>) {
my ($system, $name) = /^\s*([^,]*?)\s*,\s*(.*?)\s*$/;
$systems{$name} = $system;
}
close SYSTEMS;
open NAMES, "names.txt";
while(<NAMES>) {
my ($name) = /^\s*([^,]*?)\s*,/;
chomp;
print $_;
print ", $systems{$name}" if defined $systems{$name};
print "\n";
}
close NAMES;
Итак, здесь мы активно удаляем любые пробелы в начале или конце имени и системы. Есть другие способы сформировать это регулярное выражение, но это не относится к делу. Есть еще одна проблема с этим сценарием, которую вы видели, если в ваших файлах "names.txt" и / или "systems.txt" в конце была пустая строка. Предупреждения выглядят так:
Use of uninitialized value in hash element at ./exemplo3e.pl line 10, <SYSTEMS> line 4.
Use of uninitialized value in hash element at ./exemplo3e.pl line 10, <SYSTEMS> line 4.
John Doe, (555) 1234-4321, Inventory
Jane Doe, (555) 5555-5555, Sales
The Boss, (666) 5555-5555
Use of uninitialized value in hash element at ./exemplo3e.pl line 19, <NAMES> line 4.
То, что произошло здесь, это то, что в переменную "$name
" ничего не ушло, когда была обработана пустая строка. Есть много способов обойти это, но я выбираю следующее:
#!/usr/bin/perl
use strict;
use warnings;
our %systems;
open SYSTEMS, "systems.txt" or die "Could not open systems.txt!";
while(<SYSTEMS>) {
my ($system, $name) = /^\s*([^,]+?)\s*,\s*(.+?)\s*$/;
$systems{$name} = $system if defined $name;
}
close SYSTEMS;
open NAMES, "names.txt" or die "Could not open names.txt!";
while(<NAMES>) {
my ($name) = /^\s*([^,]+?)\s*,/;
chomp;
print $_;
print ", $systems{$name}" if defined($name) && defined($systems{$name});
print "\n";
}
close NAMES;
Регулярным выражениям теперь требуется как минимум один символ для имени и системы, и мы проверяем, определено ли "$name
", прежде чем мы его используем.
ЗАКЛЮЧЕНИЕ
Итак, вот основные инструменты для перевода сценария оболочки. Вы можете сделать НАМНОГО с Perl, но это был не ваш вопрос, и он все равно не подошел бы здесь.
Как основной обзор некоторых важных тем,
Сценарий Perl, который может быть атакован хакерами, должен запускаться с опцией -T, чтобы Perl жаловался на любой уязвимый ввод, который не был должным образом обработан.
Существуют библиотеки, называемые модулями, для доступа к базе данных, обработки XML и CIA, Telnet, HTTP и других протоколов. На самом деле, существует множество модулей, которые можно найти на CPAN .
Как уже упоминалось, если вы используете AWK или SED, вы можете перевести их на Perl с помощью A2P и S2P .
Perl может быть написан объектно-ориентированным способом.
Существует несколько версий Perl. На момент написания статьи стабильная версия 5.8.8 и 5.10.0 доступны. Существует также Perl 6 в разработке, но опыт научил всех не ждать его с нетерпением.
Существует бесплатная, хорошая, практичная, трудная и быстрая книга о Perl под названием Learning Perl The Hard Way . Это стиль похож на этот самый ответ. Это может быть хорошее место, чтобы пойти отсюда.
Надеюсь, это помогло.
ОТКАЗ
Я НЕ пытаюсь учить Perl, и вам понадобится иметь хотя бы некоторый справочный материал. Существуют рекомендации по хорошим привычкам Perl, например, использование «use strict;
» и «use warnings;
» в начале скрипта, чтобы сделать его менее снисходительным к плохо написанному коду, или использование STDOUT и STDERR в строках печати, чтобы укажите правильную выходную трубу.
Это то, с чем я согласен, но я решил, что это отвлечет от основной цели показа шаблонов для общих утилит сценариев оболочки.