Как заменить только первый экземпляр на grep / regex? - PullRequest
2 голосов
/ 04 июня 2019

Я пытаюсь создать одно регулярное выражение, которое генерирует два следующих сценария:

foobar_foobar_190412_foobar_foobar.jpg  =>  190412
foobar_20190311_2372_foobar.jpg         =>  20190311

Регулярное выражение, которое я придумал, близко, но я не могу понять, как заставить его выводить толькопервое число:

.*_(\d+)_(\d*).*                        =>  $1

foobar_foobar_190412_foobar_foobar.jpg  =>  190412
foobar_20190311_2372_foobar.jpg         =>  (no match)

Кто-нибудь получил идею?

Ответы [ 4 ]

2 голосов
/ 04 июня 2019

С опцией -P (регулярное выражение perl) и -o (только сопоставление):

grep -Po '^\D+\K\d+' file.txt
190412
20190311

Объяснение:

^           # beginning of line
  \D+       # 1 or more non digit, you can use \D* for 0 or more non digits
  \K        # forget all we have seen until this position
  \d+       # 1 or more digits

Редактировать в соответствии с неправильным пониманием тега grep

Вы можете сделать:

  • Найти: ^\D(\d+)_.*$
  • Заменить: $1
0 голосов
/ 04 июня 2019

Это то, что я искал:

find:    \D+_(\d+)_.*
replace: $1

Я не знал о «нецифровом» символе!

0 голосов
/ 04 июня 2019

, если вам небезразличны совпадения с подчеркиванием, вот sed версия

sed -E 's/[^0-9]*_([0-9]+)_.*/\1/' file
0 голосов
/ 04 июня 2019

Если мы хотим захватить первое число, мы, вероятно, можем использовать это простое выражение:

_([0-9]+)?_

Демо

или

.+?_([0-9]+)?_.+

Демо

и замените его на $1.

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

Демо

Этот фрагмент показывает, как работает группа захвата:

const regex = /_([0-9]+)?_/gm;
const str = `foobar_foobar_190412_foobar_foobar.jpg
foobar_20190311_2372_foobar.jpg`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}
...