当前位置: 首页 > 知识库问答 >
问题:

猫的无用用途?

魏安然
2023-03-14

这可能出现在许多常见问题解答中,而不是使用:

cat file | command

(这叫无用猫),正确的做法应该是:

command < file

在第二种“正确”的方式中,操作系统不必生成额外的进程<尽管知道这一点,我还是继续使用无用的猫,原因有二。

>

我“觉得”在某些情况下可能会更快。速度更快,因为有两个进程,第一个(cat)执行读取,第二个执行任何操作。它们可以并行运行,这意味着有时执行速度更快。

我的逻辑正确吗(第二个原因)?

共有3个答案

孔逸春
2023-03-14

为保护cat:

   < input process > output 

   process < input > output 

效率更高,但许多调用没有性能问题,所以您不必在意。

我们习惯于从左到右阅读

    cat infile | process1 | process2 > outfile

理解起来很琐碎。

    process1 < infile | process2 > outfile

必须跳过process1,然后从左向右读取。这可以通过以下方式治愈:

    < infile process1 | process2 > outfile

看起来好像有一个箭头指向左边,那里什么都没有。更令人困惑和看起来像花哨的引用是:

    process1 > outfile < infile

生成脚本通常是一个迭代过程,

    cat file 
    cat file | process1
    cat file | process1 | process2 
    cat file | process1 | process2 > outfile

当你看到自己的进步时

    < file 

甚至不起作用。简单的方法不太容易出错,符合人体工程学的命令级联对cat来说也很简单。

另一个话题是,大多数人

并将两个操作数与

(a > b) == (b < a)

我记得第一次使用

a.sh < file 

可能意味着

file > a.sh

并以某种方式覆盖我的a.sh脚本。也许这对许多初学者来说是个问题。

wc -c journal.txt
15666 journal.txt
cat journal.txt | wc -c 
15666

后者可直接用于计算。

factor $(cat journal.txt | wc -c)

当然是

< journal.txt wc -c 
15666
wc -c < journal.txt
15666
    

但谁在乎-1.5万?

如果我偶尔遇到问题,我肯定会改变我调用猫的习惯。

当使用非常大或非常多的文件时,避免cat是可以的。对于大多数问题,cat的使用是正交的,离题的,不是问题。

在每一个shell主题上开始这些无用的、无用的cat讨论只会让人讨厌和无聊。在处理绩效问题时,享受生活,等待成名的时刻。

张子墨
2023-03-14

没有!

首先,重定向在命令中的何处发生并不重要。因此,如果您希望重定向到命令的左侧,则可以:

< somefile command

与相同

command < somefile

其次,当您使用管道时,有n 1个进程和一个子shell发生。它肯定会变慢。在某些情况下,n会为零(例如,当您重定向到shell内置时),因此通过使用cat,您完全不必要地添加了一个新进程。

一般来说,每当你发现自己在使用管道时,都值得花30秒来看看是否可以消除它。(但可能不值得花超过30秒的时间。)以下是一些不必要地频繁使用管道和工艺的例子:

for word in $(cat somefile); … # for word in $(<somefile); … (or better yet, while read < somefile)

grep something | awk stuff; # awk '/something/ stuff' (similar for sed)

echo something | command; # command <<< something (although echo would be necessary for pure POSIX)

随意编辑以添加更多示例。

锺离森
2023-03-14

直到今天,我才意识到这个奖项,当时有个菜鸟试图用UOOC来证明我的一个答案。这是一个cat文件。txt | grep foo | cut…|剪切 。我对他说了一句心里话,之后才访问了他给我的链接,其中提到了该奖项的由来和实践。进一步的搜索使我想到了这个问题。有点遗憾的是,尽管有意识地考虑,但没有一个答案包含我的理由。

我回应他的时候并不是有意为自己辩护。毕竟,在我年轻的时候,我会将命令编写为grep-foo文件。txt |切割…|剪切

当我回答这个问题时,我有意识地选择使用cat,部分原因是出于“良好的品味”(用莱纳斯·托瓦尔兹的话来说),但主要是出于令人信服的功能原因。

后一个原因更重要,所以我会先把它说出来。当我提供管道作为解决方案时,我希望它是可重用的。很可能在另一条管道的末端添加一条管道或将其拼接到另一条管道中。在这种情况下,grep的file参数会破坏可重用性,如果file参数存在,很可能会在没有错误消息的情况下以静默方式进行。一、 e.grep-foo-xyz | grep-bar-xyz | wc将为您提供xyz中包含bar的行数,同时您需要同时包含foobar的行数。在使用管道中的命令之前,必须更改其参数,这很容易出错。再加上沉默失败的可能性,这就成为一种特别阴险的做法。

前一个原因也并非不重要,因为很多“好品味”仅仅是对上述无声失败等事情的直觉潜意识理由,当一些需要教育的人说“但那只猫不是没用吗”时,你无法正确思考。

但是,我也会试着意识到我提到的以前的“好品味”原因。那个原因与Unix的正交设计精神有关。grep剪切lsgrep。因此,至少grep foo file1 file2 file3违背了设计精神。正交的方式是cat file1 file2 file3|grep foo。现在,grep foo file1只是grep foo file1 file2 file3的一个特例,如果您不这样对待它,那么您至少正在使用大脑时钟周期试图避免无用的猫奖。

这就引出了一个论点,即grep-foo-file1-file2-file3是串联的,而cat-file2-file3是串联的,因此适合于cat-file1-file2-file3-code,但因为cat-file1-grep-foo中没有串联,所以我们违反了cat-file1和万能Unix的精神。好吧,如果是这样的话,那么Unix将需要一个不同的命令来读取一个文件的输出并将其输出到stdout(而不是分页或任何纯粹的输出到stdout的操作)。因此,您可能会遇到这样的情况:您说猫文件1文件2,或者说狗文件1,并认真记住避免猫文件1,以避免获得奖励,同时也避免狗文件1文件2,因为如果指定了多个文件,狗文件的设计可能会出错。

希望在这一点上,您能同情Unix设计人员,因为他们没有包含一个单独的命令来向stdout吐出一个文件,同时还为catenate命名,而不是给它取其他名称<代码>

下一个问题是,为什么让命令只吐出一个文件或将几个文件连接到标准输出,而不进行任何进一步的处理,这一点很重要?一个原因是避免让每一个在标准输入上运行的Unix命令都知道如何解析至少一个命令行文件参数,并将其用作输入(如果存在)。第二个原因是避免用户必须记住:(a)文件名参数的位置;和(b)避免上述无声管道错误。

这让我们明白了为什么grep确实具有额外的逻辑。其基本原理是允许用户流畅地使用经常使用且独立的命令(而不是作为管道)。这是正交性的轻微妥协,以显着提高可用性。并非所有命令都应该这样设计,不经常使用的命令应该完全避免文件参数的额外逻辑(请记住额外的逻辑会导致不必要的脆弱性(错误的可能性))。例外是允许文件参数,如grep的情况。(顺便说一句,请注意ls有一个完全不同的原因,不仅接受,而且几乎需要文件参数)

最后,如果指定文件参数时也可以使用标准输入,那么像grep(但不一定是ls)这样的异常命令会生成错误,那么可以做得更好。

 类似资料:
  • 问题内容: 我正在尝试使用具有相似列值的行来估算值。 例如,我有这个数据框 我想使用相似的列[‘one’]和[‘two’]的键,并且如果列[‘three’]并非完全是nan,则从具有相似的键的行中插值[ ‘3’] 这是我的愿望结果 您会看到键1和3不包含任何值,因为现有值不存在。 我试过使用groupby fillna() 这给了我一个错误。 我尝试了正向填充,这给了我一个相当奇怪的结果,那就是它

  • 我正在从pandas输出一个csv文件,其中包含一些用于latex报告的调查文本。一些响应在其响应中带有逗号,因此熊猫将数据输出为 通过将字段用双引号括起来,显然可以处理字段中的逗号。 我希望上面看起来像这样: 通过将所述字段包装在{}中,因为这是latex包可以理解的分隔符。 有没有办法告诉熊猫。要做这个吗? 我已经尝试了以下方法 当然,当我需要“}”时,它会用“{”关闭文本包装 更新当我使用p

  • 问题内容: 我有一个非常烦人的问题,我无法使用猫鼬更新任何内容。使用起来确实令人沮丧,并且文档根本​​没有帮助。 我有这个架构: 这是我要向阵列添加设备的代码: 在这一点上我得到错误: 我没有找到解释为什么发生这种情况的原因。我不得不提到该文档(数据库中几乎只有一个文档)是这个: 问题答案: 使用$ push或其他数组更新运算符将元素添加到数组。有关详细信息,请参阅http://docs.mong

  • 问题内容: 我对该方法的使用感到很困惑。这是我的用法,这是错误的: 我想要实现的只是从数据库中的事务中选择具有该用户名的事务,而我只想取出方法中列出的字段。谁能指出我该如何使用该方法?谢谢。 问题答案: 该文件说,你可以像这样实现的: 猫鼬v4.0 旧的过时的API 因此,您无需执行此操作。

  • 我试图在pandas中使用从FTP服务器读取压缩文件。zip文件只包含一个文件,这是必需的。 这是我的密码: 我得到这个错误: 我在pandas 18.1和19.0中都遇到了这个错误。我是否遗漏了什么,或者这可能是一个错误?

  • 问题内容: 我试图选择一个数据框的子集的一个子集,仅选择一些列,并在行上进行过滤。 但是,我得到了错误: 现在切片和过滤的正确方法是什么? 问题答案: 这是引入的更改,并在文档中进行了详细说明- 以前,选择带有标签列表的地方总是可以成功的,其中缺少一个或多个标签将返回成功。现在将显示一个。将来这将提出 (GH15747)。当传递带有至少1个缺失标签的标签列表时,此警告将在或 上触发以使用或。 例如