Как написать эту замену с условием

Я хочу заменить теперь в своих рабочих каталогах слово -> с $ \ to $, если слово не находится в дословной среде.

ПСЕВДОКОД

Замените все дочерние элементы -> с помощью $ \ to $ всюду, но не внутри \ begin {verbatim} … \ end {verbatim} .

Мой псевдокод perl, основанный на этом превосходном ответе

#!/usr/bin/env perl ## The target directories my @directories=("Cardiology", "Pathophysiology", "Patology and Biopsy", "Physiology", "Propedeutics", "Radiology", "Rheumatology", "Surgery"); ## Iterate over the directories foreach my $dir (@directories) { my $dd=0; ## Read the current directory opendir (my $DIR, "$path/$dir"); ## Find all files in this directory while (my $file = readdir($DIR)) { ## Skip any files that aren't .tex next unless $file =~ /\.tex$/; ## Open the file open(my $fh,"$path/$dir/$file"); while (<$fh>) { if (/\\begin{verbatim}/) { # Skip the Verbatim environment # TODO how this? # Need to tell it that you one line by one until \end{verbatim} is met, after which go normally forward. while (!/\\end{verbatim}/) { $dd++; } $dd++; } else { if ($dd==0) { $dd++; # I think we need this here to go one line after another } $string =~ s/->/$\to$/g; } } print "\n"; } 

где я не уверен насчет самого внутреннего псевдокода во время -loop:

  while (<$fh>) { if (/\\begin{verbatim}/) { # Skip the Verbatim environment # TODO how this? # Need to tell it that you one line by one until \end{verbatim} is met, after which go normally forward. while (!/\\end{verbatim}/) { $dd++; } $dd++; } else { if ($dd==0) { $dd++; # I think we need this here to go one line after another } $string =~ s/->/$\to$/g; } } 

Как вы можете написать такой псевдокод с условием?

Предполагая, что ваша оболочка bash, это может быть однострочный:

 perl -i.bak -pe ' /\\begin\{verbatim\}/../\\end\{verbatim\}/ or s/->/\$\\to\$/g ' {Cardiology,Pathophysiology,"Patology and Biopsy",Physiology,Propedeutics,Radiology,Rheumatology,Surgery}/*.tex 

Обратите внимание, что {...} является квантором регулярных выражений, поэтому скобки должны быть экранированы.


Я бы написал ваш код как:

 my @directories=( "Cardiology", "Pathophysiology", "Patology and Biopsy", "Physiology", "Propedeutics", "Radiology", "Rheumatology", "Surgery" ); chdir $path or die "cannot chdir '$path'"; foreach my $dir (@directories) { opendir my $DIR, $dir or die "cannot opendir '$dir'"; while (my $file = readdir($DIR)) { my $filepath = "$dir/$file"; next unless -f $filepath and $filepath =~ /\.tex$/; open my $f_in, "<", $filepath or die "cannot open '$filepath' for reading"; open my $f_out, ">", "$filepath.new" or die "cannot open '$filepath.new' for writing"; while (<$fh>) { if (not /\\begin\{verbatim\}/ .. /\\end\{verbatim\}/) { s/->/\$\\to\$/g; } print $f_out; } close $f_in or die "cannot close '$filepath'"; close $f_out or die "cannot close '$filepath.new'"; rename $filepath, "$filepath.bak" or die "cannot rename '$filepath' to '$filepath.bak'"; rename "$filepath.new", $filepath or die "cannot rename '$filepath.new' to '$filepath'"; } closedir $DIR or die "cannot closedir '$dir'"; } 

Я бы продолжал делать больше OO:

 use autodie qw(:io); use Path::Class; foreach my $dir ( "Cardiology", "Pathophysiology", "Patology and Biopsy", "Physiology", "Propedeutics", "Radiology", "Rheumatology", "Surgery" ) { my $directory = dir($path, $dir); while (my $file = $directory->next) { next unless -f $file and $file =~ /\.tex$/; my $f_out = file("$file.new")->open('w'); for ($file->slurp) { /\\begin\{verbatim\}/ .. /\\end\{verbatim\}/ or s/->/\$\\to\$/g; $f_out->print; } $f_out->close; rename "$file", "$file.bak"; rename "$file.new", "$file"; } }