我看过很多例子,但我似乎无法做到这一点。 grep 可以只输出匹配的指定分组吗? 例如看起来它应该可以工作,但我得到的是错误或根本没有输出。
我想要做:
pathname="/a/long/path/of/mine/2x02 - bar.mp4"
所有示例都将是长路径、一位或两位数字、x,然后是 2 位数字,后跟空格、a - 和文件名。
我想解析它的 02 值: https://regex101.com/ 表明在本例中 \d{1,2}x(\d\d) 应该匹配 1 = 02。
我不知道的是如果我有
echo "$pathname" | sed -n 's/.*\d{1,2}x\(\d\d\)/\1/p'
或者
echo $pathname | grep -oP '\d{1,2}x(\d\d)'
我什么也没得到。我可以:
echo $pathname | grep -oP '(\d\d)'
但在某些情况下,一行中可能还有其他 2 位数字值,就像我有
/a/long/path/of/mine/12x02 - bar.mp4
在这种情况下,我认为上面不会指定第二个匹配项,所以我更喜欢更具体的正则表达式...如果我可以使用匹配组或其他东西。我正在尝试在 Scientific Linux 7.1 上的 bash 中执行此操作。
答案1
正如您使用grep
PCRE ( -P
) 一样,您可以使用以下正则表达式模式:
grep -Po '\d{1,2}x\K\d{2}(?= )' <<<"$pathname"
\d{1,2}x
将匹配后跟的一位或两位数字x
,然后\K
将放弃匹配\d{2}
将精确匹配两个数字,零宽度正向先行模式(?= )
确保我们在两个数字后面有一个空格。
所以这应该满足您的要求。
例子 :
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/2x02 - bar.mp4'
02
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/34x12 - bar.mp4'
12
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/0x1 - bar.mp4'
## No match
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/00x1 - bar.mp4'
## No match
答案2
使用 sed
在基本模式下使用 sed,需要转义大括号:
$ echo "$pathname" | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*/\1/p'
02
为了更好的可移植性,我使用[[:digit:]]
代替\d
.我还添加.*
到末尾以删除尾随文本。
使用grep -P
grep -P
支持后视功能,但后视文本必须具有固定长度。因此,我们可以查找x
要显示的前两位数字之前的单个数字:
$ echo "$pathname" | grep -oP '(?<=\dx)(\d\d)'
02
替代路径
上述两种方法也适用于备用路径:
$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | grep -oP '(?<=\dx)(\d\d)'
02
$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*/\1/p'
02
答案3
仅使用 posix shell
p=$pathname
p=${p##*/}
p=${p#*x}
p=${p%% *}
echo "$p"
#or on one line
p=${pathname##*/};p=${p#*x};p=${p%% *};echo "$p"