Grep 命令问题 - 来自程序输出的 Grep 文本?

Posted

技术标签:

【中文标题】Grep 命令问题 - 来自程序输出的 Grep 文本?【英文标题】:Grep command questions - Grep text from program output? 【发布时间】: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

我的想法

    Grep .json 和 .description 文件路径,以便在以后的 grep 命令中使用。 运行以下脚本的工作版本,它会在 .description 文件中添加描述文本上方的新文本。 (将 .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 【参考方案1】:

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

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

类似这样的:

    grep [info] Writing video description metadata as JSON to: 之后的所有内容,即/Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).info.json$jsonfile 从第 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 解析器。我会推荐xidel。

$ 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' 这个网站不像一个论坛。如果您还有其他问题,那么您必须开始一个新问题。回答一个问题不应包含另一个问题。

以上是关于Grep 命令问题 - 来自程序输出的 Grep 文本?的主要内容,如果未能解决你的问题,请参考以下文章

Linux每天一个命令:grep

Linux安全基础:grep命令的使用

Linux grep/egrep命令详解

'grep' 不是内部或外部命令,也不是可运行的程序 或批处理文件

grep与正则表达式

Linux中的find和grep命令对查找到的文件如何处理啊