Замените все совпадения, КРОМЕ первого совпадения, в нескольких файлах на perl

#perl

#perl

Вопрос:

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

В настоящее время я использую: perl -pi -w -e 's/THING/SOMETHING_ELSE/g;' ./src/**/*.py

Практический пример:

 from stuff import THING  print(f"use {THING} here") print(f"use {THING} there") print(f"use {THING} everywhere")  

Должно стать:

 from stuff import THING  print(f"use {SOMETHING_ELSE} here") print(f"use {SOMETHING_ELSE} there") print(f"use {SOMETHING_ELSE} everywhere")  

Ответ №1:

Вам придется проверить /THING/ , прежде чем делать s/THING/.../ это .

Вот как будет выглядеть сценарий thing-to-other , который вы затем можете назвать как thing-to-other ./src/**/*.py

 #!/bin/env perl -i -p  if ( /THING/ ) {  if ( $seen{$ARGV}   ) {  s/THING/SOMETHING_ELSE/g;  } }  

Обратите внимание, что я избавился от -w этого, потому что использование %seen хэша выдаст предупреждение. %seen Хэш отслеживает, сколько раз в каждом входном файле ( $ARGV ) вы видели /MATCH/ .

Если вам действительно нужно, чтобы это был однострочный:

 perl -i -p -e'if (/THING/) {if($seen{$ARGV}  ){s/THING/SOMETHING_ELSE/g}}'  

Комментарии:

1. Обратите внимание, что это, скорее всего, не выполнит задачу, если что-то появится в любом другом случае, кроме фактической строки, которую операция пытается пропустить. Это может быть в комментарии, в качестве подстроки в чем-то другом и так далее.

2. Действительно. OP может изменить эту проверку на /ВЕЩЬ/ на более конкретный шаблон, который затем установит флаг для каждого файла, который сообщит, следует ли выполнять замену или нет.

Ответ №2:

Похоже, ты хочешь пропустить from реплику, так что я бы просто пропустил их. Это выражение либо соответствует этому from , либо пытается выполнить подстановку. То есть подстановка не предпринимается ни в одной строке, которая начинается с from :

 $ perl -pi -w -e 'm/^froms/ or s/bTHINGb/SOMETHING_ELSE/g;' test.py from stuff import THING  print(f"use {SOMETHING_ELSE} here") print(f"use {SOMETHING_ELSE} there") print(f"use {SOMETHING_ELSE} everywhere")  

Это пропускает каждую from строку, поэтому, если вы хотите изменить другие from строки, это не сработает.

Обратите внимание, что я также использую b слово «границы привязки THING «. В противном случае, вы получите то, что я получил, я снова запустил программу: SOMESOMETHING_ELSE_ELSE 🙂

Существуют различные другие способы выполнения этой задачи, но они не так хороши, как однострочные.