Существует ли простой способ сделать объемную текстовую замену файла на месте?

Кнопка ImageButton доступна только в Xamarin. Формы 3.4.

Проверьте вашу версию, скорее всего она устарела, а ImageButton недоступна в более низких версиях

12
задан Peter Mortensen 4 July 2016 в 19:29
поделиться

6 ответов

Если Вы присваиваетесь @ARGV перед использованием *ARGV (иначе ромб <>), $^I/-i будет работать над теми файлами вместо того, что было указано на командной строке.

use File::Find::Rule;
use strict;

@ARGV = (File::Find::Rule->file()->name('*.cs', '*.aspx', '*.ascx')->in('.'));
$^I = '.bak';  # or set `-i` in the #! line or on the command-line

while (<>) {
    s/thisgoesout/thisgoesin/gi;
    print;
}

Это должно сделать точно, что Вы хотите.

Если Ваш шаблон может охватить несколько строк, добавьте в a undef $/; перед <> так, чтобы Perl воздействовал на целый файл за один раз вместо линию за линией.

13
ответ дан 2 December 2019 в 04:34
поделиться

Можно интересоваться File::Transaction::Atomic или File::Transaction

РЕЗЮМЕ для F:: T:: взгляды, очень похожие на то, что Вы пытаетесь сделать:

  # In this example, we wish to replace 
  # the word 'foo' with the word 'bar' in several files, 
  # with no risk of ending up with the replacement done 
  # in some files but not in others.

  use File::Transaction::Atomic;

  my $ft = File::Transaction::Atomic->new;

  eval {
      foreach my $file (@list_of_file_names) {
          $ft->linewise_rewrite($file, sub {
               s#\bfoo\b#bar#g;
          });
      }
  };

  if ($@) {
      $ft->revert;
      die "update aborted: $@";
  }
  else {
      $ft->commit;
  }

Пара, что с File::Find Вы уже записали, и необходимо быть хорошими для движения.

7
ответ дан 2 December 2019 в 04:34
поделиться

Можно использовать Связь:: Файл, чтобы масштабируемо получить доступ к большим файлам и изменить их на месте. См. страницу справочника (человек 3perl Связь:: Файл).

6
ответ дан 2 December 2019 в 04:34
поделиться

Вы могли использовать find:

find . -name '*.{cs,aspx,ascx}' | xargs perl -p -i.bak -e "s/thisgoesout/thisgoesin/gi"

Это перечислит все имена файлов рекурсивно, затем xargs считает его stdin и выполнит остаток от командной строки с именами файлов, добавленными на конце. Одна хорошая вещь о xargs это, выполнит командную строку несколько раз, если командная строка, которую это создает, станет слишком длинной для выполнения сразу.

Обратите внимание, что я не уверен ли find полностью понимает все методы оболочки выбора файлов, поэтому если вышеупомянутое не работает затем, возможно, попытка:

find . | grep -E '(cs|aspx|ascx)$' | xargs ...

При использовании конвейеров как это мне нравится создавать командную строку и выполнять каждую часть индивидуально перед продолжением, удостоверяться, что каждая программа получает вход, который это хочет. Таким образом, Вы могли выполнить часть без xargs сначала проверять его.

Мне просто пришло в голову, что, хотя Вы не сказали так, Вы находитесь, вероятно, в Windows из-за суффиксов файла, которые Вы ищете. В этом случае вышеупомянутый конвейер мог быть выполнен с помощью Cygwin. Возможно записать сценарий Perl, чтобы сделать то же самое, когда Вы начали делать, но необходимо будет сделать оперативное редактирование себя, потому что Вы не можете использовать в своих интересах -i переключатель в той ситуации.

2
ответ дан 2 December 2019 в 04:34
поделиться

Изменение

foreach my $f (@files){
    if ($f =~ s/thisgoesout/thisgoesin/gi) {
           #inplace file editing, or something like that
    }
}

Кому:

foreach my $f (@files){
    open my $in, '<', $f;
    open my $out, '>', "$f.out";
    while (my $line = <$in>){
        chomp $line;
        $line =~ s/thisgoesout/thisgoesin/gi
        print $out "$line\n";
    }
}

Это предполагает, что шаблон не охватывает несколько строк. Если шаблон мог бы охватить строки, необходимо будет хлебать в содержании файла. ("хлебайте", довольно общий термин Perl).

Громко жевание не на самом деле необходимо, я был просто укушен строками, которые не были chompредактор слишком много раз (если Вы отбрасываете chomp, изменение print $out "$line\n"; кому: print $out $line;).

Аналогично, можно измениться open my $out, '>', "$f.out"; кому: open my $out, '>', undef; открыть временный файл и затем скопировать тот файл назад по оригиналу, когда замена сделала. На самом деле, и особенно если Вы хлебаете в целом файле, можно просто сделать замену в памяти и затем переписать исходный файл. Но я сделал достаточно ошибок при выполнении этого, что я всегда пишу в новый файл и проверяю содержание.


Отметьте, я первоначально имел если оператор в том коде. Это было, скорее всего, неправильно. Это только скопировало бы по строкам, которые соответствовали регулярному выражению "thisgoesout" (замена его с "thisgoesin", конечно) в то время как тихо пожирание остальные.

4
ответ дан 2 December 2019 в 04:34
поделиться

Благодаря ephemient по этому вопросу и по этому ответу, я получил это:

use File::Find::Rule;
use strict;

sub ReplaceText {
    my $regex = shift;
    my $replace = shift;

    @ARGV = (File::Find::Rule->file()->name('*.cs','*.aspx','*.ascx')->in('.'));
    $^I = '.bak';
    while (<>) {
        s/$regex/$replace->()/gie;
        print;
    }
}

ReplaceText qr/some(crazy)regexp/, sub { "some $1 text" };

Теперь я могу даже циклично выполниться через хеш, содержащий regexp => записи нижних индексов!

1
ответ дан 2 December 2019 в 04:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: