Замените только первое совпадение в нескольких файлах на perl

#regex #perl #replace

#регулярное выражение #perl #заменить

Вопрос:

Мне нужно заменить немного текста в нескольких файлах css, но только в первом случае.

Я попытался заменить с:

 perl -pi -e 's/(width:).*;/$1 100%;/' filename.css
  

Но это заменяет значение после каждого появления ‘width:’ в файле, даже если я не использую модификатор /g .
Я запускаю это на недавнем компьютере с Ubuntu.

Ответ №1:

Никто не обратился к подтексту вашего фактического вопроса о названии. Я рекомендую тот же подход, который использовался здесь, только измененный:

 perl -pie '!$subbed{$ARGV} and s/(width:).*;/$1 100%;/ and $subbed{$ARGV}  ' *.css
  

Безразмерное $ARGV — это имя текущего файла. Таким образом, для каждого файла вы заменяете только первое вхождение. «Глобус» *.css отправит несколько файлов. Если вы выполните скалярное переключение, которое предлагают другие пользователи, вы измените только первое вхождение в первом файле с помощью этого шаблона. (Хотя, возможно, это то, что вы хотите.)

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

1. Хорошее решение. Я не знал, что это $ARGV содержит имя текущего файла.

2. 1, передача нескольких файлов в однострочный формат очень полезна. Вы случайно не знаете способ получить больше файлов, чем *.css , например, все файлы в myfolder , повторно используя подкаталоги? Да, звучит похоже grep , но perl может сделать больше. 🙂 Например, вместо того, чтобы *.css я пытался ls *.css , оно выдало мне предупреждение, но выполнило работу над содержимым файлов. Отсутствие одного ингредиента делает это без предупреждения.

3. @zx81: *.cc Расширяется не perl, а операционной системой. Или, в случае Windows, вообще не используйте. Выполнение этого внутри однострочника, когда он просто ожидает обработки каждой строки, сложнее и больше связано с модулем. Вы могли бы поместить что-то в начальный блок для загрузки @ARGV , но это становится более сложным.

Ответ №2:

Если вы читаете в режиме абзаца, каждый файл состоит всего из одной строки; следовательно, s /// без модификатора /g заменит первый экземпляр в каждом файле, а затем перейдет к следующему файлу:

 perl -0777 -pi -e's/(width:).*;/$1 100%;/' *.css
  

Ответ №3:

Вы можете остановить замену после первого совпадения:

 perl -pi -e '$a=1 if(!$a amp;amp; s/(width:).*;/$1 100%;/);' filename.css
  

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

1. Или, короче: ... -e '!$x amp;amp; s/.../.../ amp;amp; ($x=1)' . Также это работает, только если есть только один файл, как в вопросе. К сожалению, это не работает для нескольких файлов.

2. @musikk, вот почему я внес свой ответ, который будет работать для нескольких файлов.

Ответ №4:

Вы можете попробовать это:

 perl -pi -e 's/(width:).*;/$a?$amp;:  $aamp;amp;"$1 100%;"/e' filename.css
  

Ответ №5:

Может s/(width:).*;/$1 100%;/o сойдет?