ИНСТРУКЦИЯ К СКРИПТУ replacer_v2_0_1_4.pl

Содержание:

ОБЩИЙ РАЗДЕЛ

Назначение

Скрипт предназначен для в основном для пакетных замен текстовом файле.

Варианты командной строки:
replacer_v2_0_1_4.pl -rd list input.txt output.txt
replacer_v2_0_1_4.pl -rt list input.txt output.txt

replacer_v2_0_1_4.pl -rdn list input.txt output.txt
replacer_v2_0_1_4.pl -rtn list input.txt output.txt

replacer_v2_0_1_4.pl -ra list -[A-Za-z]{1,10} input.txt output.txt
replacer_v2_0_1_4.pl -rs list -[A-Za-z]{1,10} input.txt output.txt

replacer_v2_0_1_4.pl -t input.txt output.txt
replacer_v2_0_1_4.pl -f list


Список замен и входной файл должны иметь кодировку UTF-8.

1)replacer_v2_0_1_4.pl -rd list input.txt output.txt
Сделать замены в файле имеющем словарную структуру (-rd - replace dictionary) используя список замен (list).

2)replacer_v2_0_1_4.pl -rt list input.txt output.txt
Сделать замены в файле не имеющем словарную структуру (-rt - replace text) используя список (list).

3)replacer_v2_0_1_4.pl -rdn list input.txt output.txt
Сделать замены в файле имеющем словарную структуру (-rdn - replace dictionary \n) используя список замен (list), но без автоматического добавления при записи управляющих символов \x0D \x0A (\n).

4)replacer_v2_0_1_4.pl -rtn list input.txt output.txt
Сделать замены в файле не имеющем словарную структуру (-rtn - replace text \n) используя список (list), но без автоматического добавления при записи управляющих символов \x0D \x0A (\n).

5)replacer_v2_0_1_4.pl -ra list -[A-Za-z]{1,10} input.txt output.txt
-ra - replace & angle (brackets)
Произвести замены между указанными в третьем параметре командной строки HTML тэгами.
Этот режим может использоваться только если input.txt имеет словарную структуру.
<example>abcd</example> - replacer_v2_0_1_4.pl -ra list -example input.txt output.txt
<example class=name>abcd</example> - работать не будет.

6)replacer_v2_0_1_4.pl -rs list -[A-Za-z]{1,10} input.txt output.txt
-rs - replace & square (brackets)
Произвести замены между указанными в третьем параметре командной строки DSL тэгами.
Этот режим может использоваться только если input.txt имеет словарную структуру.
[p]abcd[/p] - replacer_v2_0_1_4.pl -rs list -p input.txt output.txt
[c red]abcd[/c] - работать не будет.

7)replacer_v2_0_1_4.pl -t input.txt output.txt
Получить список HTML тэгов.
input.txt обрабатывается построчно.
Соответственно тэги которые начинаются на одной строке, а заканчиваются на другой в список не попадут.

8)replacer_v2_0_1_4.pl -f list
Про это будет сказано в разделе "Использование perl кода в списке замен."

Файл имеющий СЛОВАРНУЮ СТРУКТУРУ - это файл имеющий словарную структуру - это файл в котором заглавные слова пишутся с первой позиции новой строки, а начиная со следующей строки после заголовка записывается тело статьи, причем каждая строка в нем должна отступать от первой позиции хотя бы на один пробел или табуляцию. Тело статьи простирается до заголовка следующей статьи (признаком его является символ в первой позиции, отличный от пробела или табуляции) или до конца файла. Между телом одной и заголовком следующей статьи для удобства чтения исходного текста могут быть вставлены одна или несколько пустых строк.


Форматы записей в списке замен

1)Простые замены.
^(.+?)[\t\x20]+\|[\t\x20]+(.*)$

Пример:

a	|	b
a	|	

2)Замены с использованием регулярных выражений.
^(.+?)[\t\x20]+\|([i]{0,1})\|[\t\x20]+(.*)$

Пример:

(\d)	||	$1
\[i\]	||	
^(<[a-z]+>)$		|i|	$1

|i| - игнорировать регистр.

Ниже список специальных символов, которые в регулярных выражениях следует обязательно экранировать для превращения их в литеральные (если требуется):

[]\^$.|?*+()

В правой части это можно не делать.

Пример:

(\[\]\\\^\$\.\|\?\*\+\(\))	||	[]\^$.|?*+()$1

Символ ' и " можно не экранировать в обоих частях.

Строки начинающиеся с символа # скриптом игнорируются
Если требуется что-то заменить начинающиеся с этого символа, то можно использовать подобное выражение:

\#	||	a

Символ табуляции и пробел используются для разделения левой и правой части,
поэтому если нужно заменить что-то заканчивающиеся пробелом или символом табуляции,
то нужно использовать выражения следующего вида:

(dog )	||	pig
(dog\x20)	||	pig

Если нужно заменить что-то на что-то начинающиеся с символа табуляции или пробела:

pig	||	\tdog

Возможные ошибки

- входной файл имеет кодировку UTF-16 или UTF-32 (Unicode)
- недопустимый формат командной строки или недопустимое значение какого-либо параметра.

Пример сообщения об ошибке:
"Malformed UTF-8 character (fatal) at C:\Temp\replacer_v2_0_1_4.pl line 41, line 2"
Данная ошибка была вызвана тем, что список замен содержал кириллические символы в кодировке windows-1251.

Аварийная остановка - Ctrl+C


ИСПОЛЬЗОВАНИЕ PERL КОДА В СПИСКЕ ЗАМЕН

Для понимания

Во что превращается список замен можно увидеть запустив скрипт с такой командной строкой:
replacer_v2_0_1_4.pl -f list

Результат будет записан в файл func.txt

Допустим мы имеем список замен, который содержит следующее:

dog	|	pig
^<([uib])>$	|i|	\[$1\]

Выполняем replacer_v2_0_1_4.pl -f list

Результат:

package LIST020009121{
sub SUBR920909421::replace{
my $s = shift;
$s =~ s/dog/pig/g;
$s =~ s/^<([uib])>$/\[$1\]/gis;
return $s; 
}
}

Чтобы скрипт не испортил perl код в списке замен не следует использовать логические оператор || с пробелами или табуляторами до и после, иначе скрипт примет его за разделитель.

Неправильно:
if (($a == $b) || ($c == $d))

Правильно:
if (($a == $b)||($c == $d))
if (($a == $b) or ($c == $d))

Выражения полученные из записей второго типа (с использованием регулярных выражений) содержат модификатор "s".

s - благодаря этому модификатору входной текст воспринимается как одна строка. При этом метасимвол ".'' совпадает с любым символом, если же этот модификатор выключен, то он не совпадает с разделителями строк.

g - добавляется в обоих случаях.

i - опционально.

В списке замен процедурам можно давать любые имена, в том числе и "replace".
Имена пакетов которые уже используются в скрипте:
LIST020009121
SUBR920909421
MAIN826001181
ReplaceList


undef

Если процедура SUBR920909421::replace вернет пустую строку ($s = ''), то в выходном файле будет сделана такая запись: "\n". Т. е. в файле появится пустая строка.
В выходной файл вообще ничего не будет записано если SUBR920909421::replace вернет undef ($s = undef).


Переменные

Пример №1:

$anyname::number++;
print $anyname::number;

Результат будет таким:
123456789... каждый вызов процедуры SUBR920909421::replace (сделанной из списка замен) увеличивает значение переменной $anyname::number.

Пример №2:

my $number;
$number++;
print $number;

Результат:
111111111...


Модификатор "s"

Если результат не соответствует ожиданиям, то возможно это связано с отсутствием этого модификатора, там где это необходимо.

Пример №1:

$s = "dog\n\t a domesticated canine mammal...";
if ($s =~ /^(.*)$/){print $1}

Результат: ""

Пример №2:

$s = "dog\n\t a domesticated canine mammal...";
if ($s =~ /^(.*)$/s){print $1}

Результат: "dog\n\t a domesticated canine mammal..."


Дополнительные возможности


Описанное ниже будет работать только при использовании следующих ключей: -rt и -rd

1)Если необходимо что-то скинуть в выходной файл только после того как будет обработан весь входной файл, то нужно использовать пакет "RaplaceList" и процедуру "onexit" которая возвращает массив. В самом конце работы скрипта делается проверка на наличие данной процедуры, если такая обнаружится, то содержимое полученного массива записывается в выходной файл без добавления разделителей строк в конце, это обязанность пользователя.

Пример использования:

while ($s =~ /^.*?(\&\#[\d]+\;|\&\#[\d]+|\&[a-z]+\;)(.*)$/s){
$anyname::table{"$1\n"} = '';
$s = $2;
}
#чтобы не было пустых строк
$s = undef;

sub ReplaceList::onexit{
my @k = keys %anyname::table;
return @k;
}

Возможный результат:

&#230;
&aring;
&oslash;

2)Для остановки скрипта с выводом сообщения на экран и записью его в файл error.log
достаточно инициализировать специальную переменную "errormessage" из пакета "ReplaceList"

Пример использования:

if ($ARGV[0] ne '-rt')
  {
  $ReplaceList::errormessage = "Use \'-rtn\' instead of \'$ARGV[0]\'\n";
  }

Дополнительные примеры

Пример №1:
Изменить регистр заголовков

if ($s =~ /^([^\x20\t][^\n]+)(\n.*)$/s)
   {
   my $hw = lc($1);
   $s = "$hw$2";
   }

Пример №2:
Получить спискок всех слов

while ($s =~ /^.*?([\p{L}]{1,}[\-\'\p{L}]+[\p{L}]{1,}|[\p{L}]{2,})(.*)$/s)
      {
      $anyname::table{"$1\n"} = '';
      $s = $2;
      }
      #чтобы не было пустых строк
      $s = undef;

sub ReplaceList::onexit{
my @k1 = keys %anyname::table;
my @k2 = sort { $a cmp $b } @k1;
return @k2;
}

Пример №3:
Вытащить из файла все HTML сущности и сделать список замен

while ($s =~ /^.*?(\&\#[\d]+\;|\&\#[\d]+|\&[a-z]+\;)(.*)$/s){
$anyname::table{"$1"} = '';
$s = $2;
}
#чтобы не было пустых строк
$s = undef;


sub ReplaceList::onexit{
my @k1 = keys %anyname::table;
use HTML::Entities();
my @k2;
foreach(@k1)
       {
       my $t = HTML::Entities::decode($_);
       push @k2, "$_\t\|\t$t\n";
       }
return @k2;
}

Возможный результат:

&aring;	|	å
&#230	|	æ
&#230;	|	æ
&oslash;	|	ø

Пример №4:
Произвести замену между указанными тэгами

sub replacelist{
my $s = shift;

d | 1
o | 2
m | 4

return $s;
}


my $ot = '[p]';
my $ct = '[/p]'; 

$s =~ s/,/\&\#44;/g;
$s =~ s/(\Q$ot\E)/,$1/gi;
$s =~ s/(\Q$ct\E)/$1,/gi;

my @temparr = split(/,/, $s);

for (my $i = 0; $i < @temparr; $i++)
    {
     if ($temparr[$i] =~ /^\Q$ot\E(.+)\Q$ct\E$/is)
        {
        my $between = $1;
        $between =~ s/\&\#44;/,/g;
        $between = replacelist($between);
        $temparr[$i] = "$ot$between$ct";
        $temparr[$i] =~ s/\&\#44;/,/g;
        }
    }
$s = join("", @temparr);
@temparr = ();
$s =~ s/\&\#44;/,/g;

Пример №5:
Получить список всех символов и фрагментов которые встречаются между указанными тэгами

sub replacelist{
my $s = shift;
#удаляем другие тэги
\[(sup|sub|i|b|u)\]	|i|	
return $s
              }

my $ot = '[p]';
my $ct = '[/p]'; 

$s =~ s/,/\&\#44;/g;
$s =~ s/(\Q$ot\E)/,$1/gi;
$s =~ s/(\Q$ct\E)/$1,/gi;

my @temparr = split(/,/, $s);

foreach (@temparr)
    {
     if ($_ =~ /^\Q$ot\E(.+)\Q$ct\E$/is)
        {
        my $between = $1;
        $between =~ s/\&\#44;/,/g;
        $between = replacelist($between);
        $hash::table1{$between} = '';
          my @char_array = split(//, $between);
          foreach(@char_array)
             {
             $hash::table2{$_} = '';
             }


        }
    }
#чтобы не было пустых строк
$s = undef;

sub ReplaceList::onexit{
my @r;
my @k1 = keys %hash::table2;
my @k2 = sort { $a cmp $b } @k1;
@r = @k2;
push @r, "\n\nFRAGMENTS:\n";
@k1 = keys %hash::table1;
my @k2 = sort { $a cmp $b } @k1;
foreach(@k2)
{
push @r, "$_\n";
}
if (@r > 0){$r[0] = "SYMBOLS:\n$r[0]"};
return @r;


}

Возможный результат:

SYMBOLS:
acdgiopt

FRAGMENTS:
cat
dog
pig

Пример №6:
Получить список всех символов встречающихся в каком-либо текстовом файле.

#COMMAND LINE: 
#replacer_v2_0_1_4.pl -rt list.txt input.txt output.txt
#------------------------------------------------------

sub codepoint_hex {
	if (my $char = shift) {
		return sprintf '%2.2x', unpack('U0U*', $char);
	}
}

sub pad {
	my $str = shift;
	while (length $str < 4){
		$str = "0$str";
	}
return "0x$str";
}


my @arr = split(//, $s);
foreach(@arr){
	$pack::hash{"$_"}='';
}
$s=undef;

sub ReplaceList::onexit{
	use Encode;
	use charnames ':full';
	my @k = keys %pack::hash;
	my @sorted = sort{$a cmp $b} @k;
	foreach my $r (@sorted)
	{
		my $cp = pad(codepoint_hex($r));
		my $oc = encode("UTF-8", $r);
		my $h = unpack("H*", $oc);
		my $name = charnames::viacode($cp);
		$r = "$r\t$cp\t$h\t$name\n";
	}
return @sorted;
}

Возможный результат:

÷	0x00f7	c3b7	DIVISION SIGN
ø	0x00f8	c3b8	LATIN SMALL LETTER O WITH STROKE
û	0x00fb	c3bb	LATIN SMALL LETTER U WITH CIRCUMFLEX
ü	0x00fc	c3bc	LATIN SMALL LETTER U WITH DIAERESIS
ą	0x0105	c485	LATIN SMALL LETTER A WITH OGONEK
Ć	0x0106	c486	LATIN CAPITAL LETTER C WITH ACUTE
ć	0x0107	c487	LATIN SMALL LETTER C WITH ACUTE
ę	0x0119	c499	LATIN SMALL LETTER E WITH OGONEK
Ł	0x0141	c581	LATIN CAPITAL LETTER L WITH STROKE
ł	0x0142	c582	LATIN SMALL LETTER L WITH STROKE
ń	0x0144	c584	LATIN SMALL LETTER N WITH ACUTE
ŋ	0x014b	c58b	LATIN SMALL LETTER ENG
œ	0x0153	c593	LATIN SMALL LIGATURE OE

ДОПОЛНЕНИЕ

На Windows скрипт будет удобнее запускать если создать batch файл с таким содержанием:

@ECHO OFF
if "%1" == "-h" (
	start firefox.exe полный_путь\readme.htm
) ELSE (
	полный_путь\replacer_v2_0_1_4.pl %*
)

Этот файл нужно поместить в папку C:\Windows\System32\ и заменить "полный_путь" на реальный.

Можно также заменить "firefox.exe" на другой браузер.

После этого скрипт можно будет запускать из любого места используя, например, такую командную строку:
repl -rt list input.txt output.txt

Вызов справки: repl -h

Вариант для Linux:

function replacer()
{
clear
if [[ $# -eq 1 ]] && [[ "$1" -eq "-h" ]]; then
	(firefox полный_путь/readme.htm >/dev/null 2>&1 &)
else
	perl полный_путь/replacer_v2_0_1_4.pl "$@"
	echo ''
	echo "$(tput sgr 0)$(tput setaf 3)Press Enter to return$(tput sgr 0)"
	read input
fi	
}


alias repl=replacer

Вышеприведенный код нужно добавить в .bashrc файл.