/ / Регекс Perl замінити несподівано двічі з опцією "g" - регулярний вираз, perl, bash

Регулярний вираз Perl несподівано двічі замінюється опцією "g" - regex, perl, bash

Тож у мене папка з більшою кількістю папок. Я хотів сказати другові, що вони повинні мати замість папок, у яких кожна з вихідних файлів, лише вихідні файли, кожна з яких має кілька функцій;

тобто замість цього:

src/
load_of_functions/
function1.py
function2.py
function3.py
function4.py
load_more_functions/
function5.py
function6.py
function7.py
even_more_funcitons/
function9.py
function10.py

що вони повинні мати це:

src/
load_of_functions.py
load_more_functions.py
even_more_funcitons.py

Тож я зайшов у довідник, і зробив один лайтер, щоб отримати імена директорів, які слід помістити в електронний лист;

$ ls -l | grep ^d | awk "{print $9}" | perl -pe "s/(.*)/1.py/g"

ls -l щоб отримати файли та всю інформацію grep ^d щоб зберегти тільки дрірс awk "{print $9}" надрукувати лише 9-й стовпчик - тобто ім’я реж і perl -pe "s/(.*)/1.py/g" щоб додати ".py" до кожного рядка.

коли я це роблю, я отримую це:

$ ls -l | grep ^d | awk "{print $9}" | perl -pe "s/(.*)/1.py/g"
1.py.py
10.py.py
2.py.py
3.py.py
4.py.py
5.py.py
6.py.py
7.py.py
8.py.py
9.py.py

Я розумію, що я не розбираю файл, але роблю це по черзі, так що g для глобального не потрібно. Тому я виймаю це, і це прекрасно працює.

Це добре.

Але чому він робить заміну двічі, коли я ставив g в? Це для мене немає сенсу!

Відповіді:

4 для відповіді № 1

.* відповідає нулю або більше символів, що означає, що він може відповідати нульовим символам.

Скажімо, у вас є

$_ = "abc";
s/(.*)/1.py/g;

Перший раз, коли він шукає відповідність, він відповідає substr($_,0,3), потім /g змушує його перевірити ще одну відповідність, починаючи з позиції 3 або пізніше.

Вдруге він шукає відповідність substr($_,3,0), потім /g змушує його перевірити ще одну відповідність, починаючи з позиції 3 або пізніше.

Третій раз, коли він шукає відповідність, він відповідає substr($_,3,0). Однак двигун відмовляється відповідати одній і тій же підрядці (визначеній як однакова вихідна позиція і однакову довжину) двічі, тому вона виходить з ладу.

Рішення:

s/(.*)/1.py/;    # Poor
s/^(.*)/1.py/g;  # Poor
s/^(.*)/1.py/;   # Ok
s/$/.py/;         # Better
$_ .= ".py";      # Best if -l was present