如何只用 grep/regex 替换第一个实例?

How to replace only first instance with grep/regex?

我正在尝试设计一个产生以下两种情况的正则表达式:

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

我想出的正则表达式很接近,但我不知道如何让它只输出第一个数字:

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

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

有人知道吗?

如果我们希望捕获第一个数字,我们可以使用这个简单的表达式:

_([0-9]+)?_

Demo

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

Demo

并将其替换为</code>。 </p> <h3>正则表达式电路</h3> <p><a href="https://jex.im/regulex/#!flags=&re=%5E(a%7Cb)*%3F%24" rel="nofollow noreferrer">jex.im</a> 可视化正则表达式:</p> <p><a href="https://i.stack.imgur.com/jRf3x.png" rel="nofollow noreferrer"><WBIMG:11702174-1.png></a></p> <h3>演示</h3> <p>这段代码只是展示了捕获组的工作原理:</p> <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code"> <pre><code>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}`); }); }

使用选项 -P(perl 正则表达式)和 -o(only-matching):

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标签的误解编辑

你可以这样做:

如果您关心下划线匹配,这里是 sed 版本

sed -E 's/[^0-9]*_([0-9]+)_.*//' file

这就是我要找的东西:

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

我不知道 "non-digit" 这个角色!