更好的正则表达式来获取括号中的值

Dan*_*oux 8 regex awk grep

我有一个 M3U 播放列表,如下所示:

#EXTM3U
#EXTINF:-1 tvg-id="wsoc.us" tvg-name="ABC 9 (Something) (WSOC)" tvg-logo="" group-title="US Locals",ABC 9 (Something) WSOC (WSOC) 
http://some.url/1
#EXTINF:-1 tvg-id="wbtv.us" tvg-name="CBS 3 WBTV (WBTV)" tvg-logo="" group-title="US Locals",CBS 3 WBTV (WBTV)
http://some.url/2
#EXTINF:-1 tvg-id="wcnc.us" tvg-name="NBC (Hey) 36 WCNC (WCNC)" tvg-logo="" group-title="US Locals (Something here)",NBC 36 (Hey) WCNC (WCNC)
http://some.url/3
#EXTINF:-1 tvg-id="wjzy.us" tvg-name="FOX 46 WJZY (Shout Out) (WJZY)" tvg-logo="" group-title="US Locals",FOX 46 WJZY (Shout Out) (WJZY)
http://some.url/4
Run Code Online (Sandbox Code Playgroud)

我希望获取 tvg-name 字段中不带括号的最后一个条目 - 例如,WSOC 和 WBTV 和 WCNC 等。

这有效:

grep -Po 'tvg-name=\".*?\"'  Playlist.m3u | awk -F'(' '{print $NF}' | cut -f1 -d")" | sort -u
Run Code Online (Sandbox Code Playgroud)

但我知道一定有比使用 grep、awk 和 cut 更好的方法。这让我抓狂。

Gil*_*not 4

仅使用正则表达式GNU grep

grep -oP 'tvg-name.*\(\K\w+(?=\))' /tmp/file.m3u
Run Code Online (Sandbox Code Playgroud)

正则表达式匹配如下:

节点 解释
tvg-name 'tvg-名称'
.* 除 \n 之外的任何字符(0 次或多次(匹配尽可能多的数量))
\(
\K 重置比赛的开始(什么是Kept)作为使用后视断言的更短替代方案:环顾四周支持正则表达式中的 K
\w+ 单词字符(az、AZ、0-9、_)(1 次或多次(匹配尽可能多的数量))
(?= 向前看是否有:
\)
) 前瞻结束

或者使用适当的 m3u 解析器

需要安装CPAN模块

cpan Parse::M3U::Extended 
Run Code Online (Sandbox Code Playgroud)

#!/usr/bin/env perl

use strict; use warnings;

use Parse::M3U::Extended qw(m3u_parser);
use File::Slurp;
use feature 'say';
my $m3u = read_file('/tmp/file.m3u');
my @items = m3u_parser($m3u);

foreach my $item (@items) {
    if ($item->{type} eq "directive" and $item->{tag} eq "EXTINF") {
        $_ = $item->{value};
        s/.*\((\w+)\)/$1/;
        say;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做的优点是可以以可靠的方式重用于其他用例,而 random 等则不是这样awksed......

输出:

WSOC 
WBTV
WCNC
WJZY
Run Code Online (Sandbox Code Playgroud)