问题描述
我正在编写一个脚本来解析 m3u 文件。 目标是检索变量标签和 url。 我用 this file.
测试过#!/bin/bash
echo "name,tvg-id,tvg-name,tvg-country,group-title,languages,url"
while IFS= read -r line; do
tags_detect="$(echo "$line" | grep -Eo '^#EXTINF:')"
if [[ -n ${tag_detect} ]]; then
get_chno="$(echo "$line" | grep -o 'tvg-chno="[^"]*' | cut -d '"' -f2)"
get_id="$(echo "$line" | grep -o 'tvg-id="[^"]*' | cut -d '"' -f2)"
get_logo="$(echo "$line" | grep -o 'tvg-logo="[^"]*' | cut -d '"' -f2)"
get_grp_title="$(echo "$line" | grep -o 'group-title="[^"]*' | cut -d '"' -f2)"
get_title="$(echo "$line" | grep -o ',[^*]*' | cut -d ',' -f2)"
get_tvg_name="$(echo "$line" | grep -o 'tvg-name="[^"]*' | cut -d '"' -f2)"
get_country="$(echo "$line" | grep -o 'tvg-country="[^"]*' | cut -d '"' -f2)"
get_language="$(echo "$line" | grep -o 'tvg-language="[^"]*' | cut -d '"' -f2)"
phrase="${get_title},${get_id},${get_tvg_name},${get_country},${get_grp_title},${get_language}"
else
url="$line"
fi
echo "${phrase},${url}"
done <"${1}"
所以,没有“如果”它可以工作,但我没有网址。 我添加了一个“IF”和...:
,#EXTM3U
4 Turk Music,4TurkMusic.fr,4 Turk Music,FR;TK,Music,Turkish,http://51.210.199.30/hls/stream.m3u8
Alpe d’Huez TV,AlpedHuezTV.fr,Alpe d’Huez TV,FR,french,https://edge10.vedge.infomaniak.com/livecast/ik:adhtv/chunklist.m3u8
...它坏了,我没有发现我的错误。
期望输出:
4 Turk Music,http://1.2.3.4/hls/stream.m3u8
Alpe d’Huez TV,https://edge10.vedge.infomaniak.com/livecast/ik:adhtv/chunklist.m3u8
我不明白我的错误。
解决方法
您可能最好使用更强大的语言,例如 Perl。
#! /usr/bin/perl
use strict;
use warnings;
print "name,tvg-id,tvg-name,tvg-country,group-title,languages,url\n";
my %tags;
my $title;
while (<>)
{
next if /^#EXTM3U/;
if (s/^#EXTINF:-1//) {
%tags = ();
$tags{$1} = $2 while (s/\s*(\S+)="([^"]*)"//);
($title) = $_ =~ /,(.*)/;
} else {
print join (',',$title,$tags{'tvg-id'},$tags{'tvg-name'},$tags{'tvg-country'},$tags{'group-title'},$tags{'tvg-language'},$_);
}
}
,
快速重构(未经测试)-
declare -A tag
while IFS= read -r line; do
case "$line" in
\#EXTINF:*)
if [[ "$line" =~,([^*]+) && -n "${BASH_REMATCH[0]}" ]]; then
tag[title]="${BASH_REMATCH[0]}"
phrase="${tag[title]}"
fi
for id in tvg-id tvg-name tvg-country group-title tvg-language tvg-chno tvg-logo; do
pat=$id'="([^"]+)"'
[[ "$line" =~ $pat ]] && tag[$id]="${BASH_REMATCH[0]}";
phrase="$phrase,${tag[$id]}"
done
phrase="${phrase%,${tag[tvg-chno]},${tag[tvg-logo]}}"
;;
*) url="$line"
esac
echo "${phrase},${url}"
done <"${1}"
需要更多的错误检查...
,它坏了,我没有发现我的错误。
将您的脚本粘贴到 https://shellcheck.net 以进行验证/推荐。
这是我在 bash 中的做法。
#!/usr/bin/env bash
printf '%s\n' "name,url"
while IFS= read -r data; do
[[ $data != '#EXTINF:-1'* ]] && continue
IFS= read -r url && [[ $url != 'http'* ]] && echo "$url" && continue
if [[ "$data" == '#EXTINF:-1'* && "$url" == 'http'* ]]; then
title=${data#*\",}
tvg_id=${data#*tvg-id=\"} tvg_id=${tvg_id%%\"*}
tvg_name=${data#*tvg-name=\"} tvg_name=${tvg_name%%\"*}
tvg_country=${data#*tvg-country=\"} tvg_country=${tvg_country%%\"*}
group_title=${data#*group-title=\"} group_title=${group_title%%\",*}
tvg_language=${data#*tvg-language=\"} tvg_language=${tvg_language%%\"*}
printf '%s,%s,%s\n' "$title" "$tvg_id" "$tvg_name" "$tvg_country" "$group_title" "$tvg_language" "$url"
fi
done < file.txt
虽然我不确定第 233 行和第 238 行会发生什么,但该行以 #EXTVLCOPT
开头
ed
解决方案(如果可用/可接受)。
脚本,随便命名。我将它命名为 script.ed
g/^#EXTINF:-1/s/$/ /\
;/^http\(s\)\{0,1\}.*/-1;/^[^#]*$/j,s/^#EXTINF:-1 tvg-id="\([^"]*\)" tvg-name="\([^"]*\)" tvg-country="\([^"]*\)" tvg-language="\([^"]*\).* group-title="\([^"]*\)",\(.*\) \(http.*\)\{0,1\}/\6,\1,\2,\3,\5,\4,\7/
1c
name,url
.,p
Q
现在针对相关文件运行它。
ed -s file.txt < script.ed
-
从脚本中删除
,p
以使输出静音到 stdout 或者如果您对输出感到满意。 -
如果需要就地编辑,请将脚本中的
Q
更改为w
。
应该给出与 bash 解决方案或多或少相同的结果,但由于仍然未知第 233 行和第 238 行会发生什么,该行以 #EXTVLCOPT
开头