#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
🙂
Существуют различные другие способы выполнения этой задачи, но они не так хороши, как однострочные.