【问题标题】:Grep command questions - Grep text from program output?Grep 命令问题 - 来自程序输出的 Grep 文本?
【发布时间】:2020-12-23 03:29:00
【问题描述】:

我正在尝试从 json 文件 youtube-dl 中提取信息,并将其中的一些信息 grep 到 .txt 文件中。

下载视频时 youtube-dl 的输出示例。

[info] Writing video description to: /Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).description
[info] Writing video description metadata as JSON to: /Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).info.json

我的想法

  1. Grep .json 和 .description 文件路径,以便在以后的 grep 命令中使用。
  2. 运行以下脚本的工作版本,它会在 .description 文件中添加描述文本上方的新文本。
  3. (将 .description 重命名为 .txt)

我更喜欢这种方法,因为 youtube-dl 只需要运行一次。

如果有其他通用命令可以在 mac 和 Linux 上使用 grep 来简化操作,那么我认为使用它们代替 grep 没有问题。


问题

  • 如何 grep 文件路径并在下面脚本示例中描述的其他命令中使用它?
  • 如何运行下面的脚本,但在该文本文件中的当前描述文本上方添加所有信息?
  • 当它从 json 文件中获取信息时,它也会在前后获取 "。因此视频名称变为:"VIDEO NAME",但只需要 VIDEO NAME
  • 如何从 json 文件中 grep TAGS?标签在 .json 文件中如下所示:"tags": ["music", "video", "classic"]。想得到"music", "video", "classic"

脚本示例

    txtfile="$GREP_DESCRIPTION_FROM_YOUTUBE-DL_OUTPUT"
    jsonfile="$GREP_JSON_FROM_YOUTUBE-DL_OUTPUT"

    echo TITLE >> $txtfile
    grep -o '"title": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile
    
    echo CHANNEL >> $txtfile
    grep -o '"uploader": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile
    
    echo CHANNEL URL >> $txtfile
    grep -o '"uploader_url": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile
    
    echo UPLOAD DATE >> $txtfile
    grep -o '"upload_date": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile
    
    echo TAGS >> $txtfile
    grep -o '"tags": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile
    
    echo URL >> $txtfile
    echo $url >> $txtfile
    echo \ >> $txtfile
    
    echo DESCRIPTION >> $txtfile

【问题讨论】:

  • 不要使用grep 处理JSON。使用jq

标签: json bash youtube grep youtube-dl


【解决方案1】:

感谢巴尔默!这回答了我四个问题中的三个。

剩下的,我想不通的是如何从 youtube-dl 输出中获取 json 文件位置,让它在脚本中工作,以及如何在同一目录中创建一个 .txt 文件,但以 .txt 结尾。

类似这样的:

  1. grep [info] Writing video description metadata as JSON to: 之后的所有内容,即/Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).info.json
  2. $jsonfile
  3. 从第 1 点获取相同的输出,将扩展名(最后一个 .DOT 之后的所有内容)替换为 .txt,使其成为 $txtfile

用 jq 更新脚本

#! /bin/bash

    txtfile="textfile.txt"
    jsonfile="jsonfile.json"

    echo - TITLE - >> $txtfile
    jq -r '.title' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - CHANNEL - >> $txtfile
    jq -r '.uploader' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - CHANNEL URL - >> $txtfile
    jq -r '.uploader_url' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - UPLOAD DATE - >> $txtfile
    jq -r '.upload_date' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - URL - >> $txtfile
    jq -r '.webpage_url' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - TAGS - >> $txtfile
    jq -r -c '.tags' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - DESCRIPTION - >> $txtfile
    jq -r '.description' $jsonfile >> $txtfile

【讨论】:

    【解决方案2】:
    $ youtube-dl --help | grep "dump-json"
        -j, --dump-json                  Simulate, quiet but print JSON information.
    

    使用此选项,根本无需下载视频。只需将youtube-dl 的输出通过管道传输到适当的 JSON 解析器。我会推荐

    $ youtube-dl -j https://www.youtube.com/watch?v=dQw4w9WgXcQ | xidel -se '
      $json/(
        "- TITLE -",title,"",
        "- CHANNEL -",uploader,"",
        "- CHANNEL URL -",uploader_url,"",
        "- UPLOAD DATE -",upload_date,"",
        "- URL -",webpage_url,"",
        "- TAGS -",translate(serialize(tags,{"method":"json"}),"[]",""),"",
        "- DESCRIPTION -",description
      )
    '
    

    (替代格式化标签:join((tags)() ! x""{.}"",",")

    如果您已经下载了视频和 JSON(我猜是 --write-info-json),那么您可以使用 --get-filename 检索文件名:

    $ youtube-dl --get-filename https://www.youtube.com/watch?v=dQw4w9WgXcQ
    Rick Astley - Never Gonna Give You Up (Video)-dQw4w9WgXcQ.mp4
    
    $ jsonfile=$(youtube-dl --get-filename https://www.youtube.com/watch?v=dQw4w9WgXcQ)
    
    $ xidel -s "${jsonfile/.mp4/.info}.json" -e '
      $json/(
        [...]
      )
    ' > "${jsonfile/.mp4/.info}.txt"
    

    命令的输出,或“Rick Astley - Never Gonna Give You Up (Video)-dQw4w9WgXcQ.info.txt”的内容:

    - TITLE -
    Rick Astley - Never Gonna Give You Up (Video)
    
    - CHANNEL -
    RickAstleyVEVO
    
    - CHANNEL URL -
    http://www.youtube.com/user/RickAstleyVEVO
    
    - UPLOAD DATE -
    20091024
    
    - URL -
    https://www.youtube.com/watch?v=dQw4w9WgXcQ
    
    - TAGS -
    "the boys soundtrack","the boys amazon prime","Never gonna give you up the boys","RickAstleyvevo","vevo","official","Rick Roll","video","music video","Rick Astley album","rick astley official","single","album","together forever","Never Gonna Give You Up","Whenever You Need Somebody","pop","rickrolled","WRECK-IT RALPH 2","Fortnite song Fortnite item shop Fortnite time shop today Fortnite montage","Fortnite event","Fortnite dance","fortnite never gonna give you up"
    
    - DESCRIPTION -
    Rick Astley's official music video for "Never Gonna Give You Up" Listen to Rick Astley: https://RickAstley.lnk.to/_listenYD Subscribe to the official Rick As...
    

    如果您只需要此信息,则实际上不需要youtube-dl。解析 html-source 就足够了:

    $ xidel -s https://www.youtube.com/watch?v=dQw4w9WgXcQ -e '
      "- TITLE -",//meta[@itemprop="name"]/@content,"",
      "- CHANNEL -",//meta[@itemprop="channelId"]/@content,"",
      "- CHANNEL URL -",//span[@itemprop="author"]/link/@href,"",
      "- UPLOAD DATE -",//meta[@itemprop="datePublished"]/@content,"",
      "- URL -",//meta[@property="og:url"]/@content,"",
      "- TAGS -",join(//meta[@property="og:video:tag"]/x""{@content}"",","),"",
      "- DESCRIPTION -",//meta[@itemprop="description"]/@content
    '
    

    html-source 也有一个巨大的 JSON,包含你需要的所有信息。提取难度有点大,但可以做到:

    $ xidel -s https://www.youtube.com/watch?v=dQw4w9WgXcQ -e '
      parse-json(//script/extract(.,"ytInitialPlayerResponse = (\{.+\})",1))/(
        "- TITLE -",videoDetails/title,"",
        "- CHANNEL -",videoDetails/channelId,"",
        "- CHANNEL URL -",microformat//ownerProfileUrl,"",
        "- UPLOAD DATE -",microformat//publishDate,"",
        "- URL -","https://www.youtube.com/watch?v="||videoDetails/videoId,"",
        "- TAGS -",translate(serialize(videoDetails/keywords,{"method":"json"}),"[]",""),"",
        "- DESCRIPTION -",x:lines(videoDetails/shortDescription)[1]
      )
    '
    

    【讨论】:

    • 非常感谢您的意见。 ...但这是我试图创建的脚本的一部分。它创建一个包含有关下载视频的信息的文本文件。该文件应与视频位于同一文件夹中,并且与视频同名,但以 .txt 结尾。也想尽量少连接Youtube,在mac+linux上使用默认软件,脚本也要简单。如果可以将您的第一个示例输出到 txt 文件将是最好的。无需下载 json 文件。
    • youtube-dl 在下载时显示的文件的路径是这样的。所以一些如何获得其中一个,首选视频文件,然后将 mp4 更改为 txt 并将 xidel 的输出保存在那里。 [youtube] dQw4w9WgXcQ:将缩略图写入:/Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).webp [download] 目的地:/Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (视频).mp4
    • @Wogol 请参阅编辑后的答案,了解如何检索文件名。
    【解决方案3】:

    解决了下面谈到的问题。

    通过在脚本末尾添加两个 " 解决它

    ...
    ' --printed-json-format=compact >> "$textfile"
    

    谢谢雷诺!


    谢谢。现在已经尝试让它工作。它给了我一些错误,并从一些故障排除开始。还是没有运气。

    这个测试看看它是否有效。 folderurl 在脚本中较早出现,在这里是临时的。

        folder=/Users/ACCOUNT/Downloads/ytdl/
        url=https://www.youtube.com/watch?v=dQw4w9WgXcQ
        textfile=$(youtube-dl --get-filename -o $folder'%(title)s/%(title)s.txt' $url)
        $textfile
    

    输出是:

    -bash: /Users/ACCOUNT/Downloads/ytdl/Rick: No such file or directory
    

    如果我创建该文件夹,则输出为

    -bash: /Users/ACCOUNT/Downloads/ytdl/Rick: is a directory
    

    但如果我完全按照我的想法测试脚本

    youtube-dl --get-filename -o /Users/ACCOUNT/Downloads/ytdl/'%(title)s/%(title)s.txt' https://www.youtube.com/watch?v=dQw4w9WgXcQ
    

    输出是:

    /Users/ACCOUNT/Downloads/ytdl/Rick Astley - Never Gonna Give You Up (Video)/Rick Astley - Never Gonna Give You Up (Video).txt
    

    它应该是什么样子。我做错了什么?


    这是 xidel 脚本以及我如何更改它,$url>> $textfile。我使用这个脚本是因为它得到了完整的描述。

    xidel -s "$url" -e '
      let $json:=json(
            //script/extract(.,"ytplayer.config = (.+?\});",1)[.]
          )/args,
          $a:=json($json/player_response)/videoDetails,
          $b:=json($json/player_response)/microformat
      return (
        "- TITLE -",
        $a/title,"",
        "- CHANNEL -",
        $a/author,"",
        "- CHANNEL URL -",
        $b//ownerProfileUrl,"",
        "- UPLOAD DATE -",
        $b//publishDate,"",
        "- URL -",
        $json/loaderUrl,"",
        "- TAGS -",
        $a/keywords,"",
        "- DESCRIPTION -",
        $a/shortDescription
      )
    ' --printed-json-format=compact >> $textfile
    

    【讨论】:

    • 对变量使用大括号并引用它:-o '${folder}%(title)s/%(title)s.txt'
    • 这个网站不像一个论坛。如果您还有其他问题,那么您必须开始一个新问题。回答一个问题不应包含另一个问题。
    猜你喜欢
    • 2012-05-04
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    相关资源
    最近更新 更多