管道命令改变标准输出吗?

管道命令改变标准输出吗?

我尝试了三种不同的“别名”函数,通过给定参数从命令行显示图像。有人能告诉我为什么输入的处理方式与我仅将 URL 提供给最终命令时不同吗?

function xkcd() {pandoc -f html -t plain https://xkcd.com/"$1"/ | grep *.png | display;}
function xkcd() {pandoc -f html -t plain https://xkcd.com/"$1"/ | grep *.png | w3m;}
function xkcd() {pandoc -f html -t plain https://xkcd.com/"$1"/ | grep *.png | open;}
function xkcd() {pandoc -f html -t plain https://xkcd.com/"$1"/ | grep *.png | eog;}

#where $1 is a number in the range of values present in the site's structure

当我使用图像 URL 作为参数单独运行 w3m 时,它会弹出一个裁剪过的 imagemagick 小窗口,其中包含图像(该函数的预期结果)。当它从管道接收 URL 运行时(表面上),它会打开一个页面,上面只打印了 URL 文本。

运行显示也工作正常,然后使用管道出现错误:

display-im6.q16: no decode delegate for this image format `' @ error/constitute.c/ReadImage/575.

打开后给了我它的帮助对话框:

xdg-open - opens a file or URL in the user's preferred application

Synopsis

xdg-open { file | URL }

xdg-open { --help | --manual | --version }

Use 'man xdg-open' or 'xdg-open --manual' for additional info.

eog 为两者打开了一个空白窗口,因此在此过程中没有用。

我不知道我是否做错了什么,对管道期望太高,或者有一些我无法识别的简单语法错误,因为我仍在学习,但这让我发疯。

function xkcd() { pandoc -t https://xkcd.com/"$1" | grep ".png" | cat; }

按预期返回图像 URL。

function xkcd() { pandoc -t https://xkcd.com/"$1" | grep ".png" | echo; }

返回一个空白行,我猜这是问题的关键,但我希望有人可以向我解释或指出正确的方向,让我了解这里到底发生了什么?TIA。

PS:如果有帮助的话,在 debian bullseye 上使用 bash

答案1

命令行参数不是标准输入/输出。当您eog foobar使用 URL 作为命令行参数运行时,它接收该参数的方式与您使用的方式完全不同echo foobar | eog- 不像阅读将来自 stdin 的数据作为“文件”后,程序直接获得一个参数列表作为“argv”数组。

我们不期望程序会以相同的方式对待两者;事实上,大多数程序都应以相同的方式对待它们不同地。例如,ImageMagickdisplay期望从 stdin 读取原始图像数据,而不是文件名,而 EoG 根本不关心 stdin。(当然,在您自己的示例中,grep能够从 stdin 读取文本从其命令行获取正则表达式模式。)

当您有一个管道并想将其输出用作程序的命令行参数时,最常见的方法是使用工具xargs

echo https://xkcd.com/1168/ | xargs -d '\n' w3m

或者,使用 shell 的$(…)`…`运算符将程序的输出捕获到变量中:

url=$(pandoc this | grep that) && w3m "$url"
display "$(pandoc https://xkcd | grep '\.png')"

还要注意:1)grep接受正则表达式,而不是 shell 通配符;2) 未加引号的通配符由 shell 扩展,不会以“原始”形式传递给程序,除非扩展失败。

因此,如果您使用| grep *.png并在当前目录中拥有一些 PNG 文件,您的函数最终将运行| grep foo.png,而不会产生正确的输出。

如果你引用该参数以防止扩展并使用| grep "*.png",它仍然不起作用 - 它甚至不是一个有效的正则表达式(在正则表达式中,*是一个修饰符并且需要某物在它之前)。

您想使用其中之一grep ".*\.png"或者仅仅grep "\.png"使用代替。

相关内容