重定向命令的输出,就好像它是文件输入一样

重定向命令的输出,就好像它是文件输入一样

我发现自己总是必须在命令行中向上箭头并向后移动,以更改先前命令的一部分,该部分会被转移到稍后的命令grephead其他命令。

举一个简单的例子:搜索dmesg给定的字符串并且只想要最后 5 个出现的字符串。

我会这样做:

dmesg | grep -i USB | tail -n 5

但如果我想更改搜索词或我正在搜索的内容或来源,我会等待光标回溯到该行的相关部分。我想将其移至行尾,以便上面的示例可以表示为(我知道这是不正确的):

tail -n 5 < dmesg | grep -i USB(然后我可以搜索sda

正如我所说,这是一个原油例如,它表明了我想做的事情,但实际上并不是我想做的事情,即。这不是关于anddmesg的使用,而是如何在这些程序之间进行交互,并将“变量”放在末尾。greptail

这可以进一步以获取 DNS 查询的查找时间为例:

dig google.com | grep msec(让我们移动google.com到最后,以便我可以测试另一个域)通过
grep msec < dig google.com

再次,糟糕的例子。我更多地讨论的是当我在多个程序之间有输入/输出流动时

我承认我对管道和重定向只有基本的了解,可以总结为:

  • 管道 ( |)使用stdout一个程序的 来输入stdin另一个程序的
  • 重定向(>获取stdout一个程序的并将其输入到一个文件中(旁白:除了我能想到的唯一明显的地方之外,它是否可以被重定向到其他地方
    > /dev/null 或者
    > /dev/sda 或者
    > {said file}
    然而管道是程序输出作为程序输入从左到右。
  • 重定向(< (我称之为“文件作为输入”)获取文件的内容并使用它们,就像在命令行中键入它们一样

答案1

在支持(bash、ksh、zsh)的shell中<(),您可以转换

$ cmd1 | cmd2 

进入

$ cmd2 < <(cmd1)

这两者在管道方面应该是等效的。 (但是,我认为这两种形式在处理进程组和信号等事务的方式方面存在一些细微差别)。

为了更好地进行命令行编辑,我建议您探索 shell 的工具。例如,bashset -o vi允许您使用类似 vi 的快捷方式或vim直接切换到更有效地编辑命令。默认set -o emacs使用 emacs 快捷方式(搜索man bashreadline 以了解有关它们的更多信息 ( /readline))。

答案2

我经常对同一件事感到恼火,有几种处理方法:

  1. 接受它吧,有时不值得花时间去解决它。

  2. 正如 PSkocik 提到的,你可以使用例如tail -n 5 <(dmesg | grep USB)

  3. 更加熟练地使用 shell 的编辑功能 - 例如,在 bash(以及许多其他使用 readline 的程序)中,您可以使用它CtrlA来到达行首,向前ESCfESCb向后移动“单词”,以及Ctrl-XCtrl-E在 $ 中编辑当前行编辑(例如vim

还有更多可用的编辑命令,并readline在 .info 文件中完整记录。在 Debian 系统上,安装该readline-doc软件包。其他发行版可能会在 readline 包本身中包含文档,或者可能像 Debian 那样将其分开。

我还建议安装和使用pinfolynx 网络浏览器,以获得更像 lynx 的体验(在我看来,GNUinfo浏览器很糟糕,几乎无法使用)。如果它还没有在你的发行版中,你可以在http://pinfo.alioth.debian.org/

  1. readline还有一种vi编辑模式(默认是emacs类似模式),有些人更喜欢这种模式。

  2. 在简单的情况下,您可以使用快速替换:例如,如果您输入的最后一个命令是:

dmesg | grep -i USB | tail -n 5

然后输入^USB^sda^Enter将导致执行:

dmesg | grep -i sda | tail -n 5

有关这方面的更多详细信息,请参阅man bash并搜索HISTORY EXPANSION,尤其是 部分Event Designators

是的,重复这样做也会变得烦人。

  1. 对于更复杂的情况,最好的解决方案是编写一个 shell 脚本或函数来执行您想要的操作并运行它,而不是使用漫长而复杂的命令管道。

例如,编写一个名为的 shell 脚本dmesg-grep,如下所示:

#! /bin/bash

# regexp to search for is arg 1.  needs to be an extended regexp
# because we're using grep -E aka egrep.
re="$1"

# number of lines to output is optional arg 2 (default 5)
lines=${2:5}

dmesg | grep -iE "$re" | tail -n "$lines"

然后你就可以运行dmesg-grep usbdmesg-grep sda

如果您经常这样做,请bin在主目录中创建一个子目录并添加~/bin到您的默认路径(例如 in~/.bash_profile~/.bashrc)并将脚本保存在其中。

答案3

您可能认为这是一个侧面的答案,但解决方案通常是简单地在命令行中使用变量。它们不仅仅适用于 shell 脚本。例如,您正在通过反复试验开发一个复杂的“one-liner”,并且具有:

 $ some complex command using value 23 at this point

那么您只想改变命令行中间的一个值。一次编辑,然后该行就变得很容易调用,而不需要任何进一步的编辑:

 $ a=23
 $ some complex command using value "$a" at this point
 $ a=37
 $ some complex command using value "$a" at this point
 $ a=42
 $ some complex command using value "$a" at this point

$a当您需要在命令中的两个或多个位置(例如目录或文件名)时,它会更好。

相关内容