【问题标题】:Bash script, if statement in while loop, unwanted duplicate outputBash 脚本,while 循环中的 if 语句,不需要的重复输出
【发布时间】:2021-09-12 11:09:19
【问题描述】:

我正在编写一个脚本来解析 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,#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,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,4TurkMusic.fr,4 Turk Music,FR;TK,Music,Turkish,http://1.2.3.4/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

我不明白我的错误。

【问题讨论】:

    标签: bash shell if-statement while-loop m3u


    【解决方案1】:

    它坏了,我没有发现我的错误。

    将您的脚本粘贴到https://shellcheck.net 以供验证/推荐。


    这是我在 bash 中的做法。

    #!/usr/bin/env bash
    
    printf '%s\n' "name,tvg-id,tvg-name,tvg-country,group-title,languages,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,%s,%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,tvg-id,tvg-name,tvg-country,group-title,languages,url
    .
    ,p
    Q
    

    现在对有问题的文件运行它。

    ed -s file.txt < script.ed
    
    • 从脚本中删除 ,p 以使输出静音到标准输出,或者如果您对输出感到满意。

    • 如果需要就地编辑,请将脚本中的Q 更改为w


    应该给出与 bash 解决方案或多或少相同的结果,但由于仍然未知第 233 和 238 行应该发生什么,这些行以 #EXTVLCOPT 开头

    【讨论】:

    • 非常感谢,我已经在使用Shellcheck了,没有报错。
    【解决方案2】:

    您最好使用功能更强大的语言,例如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'},
                    $_);
      }
    }
    

    【讨论】:

      【解决方案3】:

      快速重构(未经测试)-

      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}"
      

      需要更多的错误检查...

      【讨论】:

      • 谢谢,不过是一样的效果。太奇怪了。
      猜你喜欢
      • 2017-01-15
      • 2014-01-21
      • 2017-08-15
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多