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"
谢谢雷诺!
谢谢。现在已经尝试让它工作。它给了我一些错误,并从一些故障排除开始。还是没有运气。
这个测试看看它是否有效。 folder
和 url
在脚本中较早出现,在这里是临时的。
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 文本?的主要内容,如果未能解决你的问题,请参考以下文章