1

考虑以下示例 Bash one-liner,其中字母“h”、“e”和“o”按顺序从单词“hello”中删除。只剩下两个“l”字母;

$ echo "hello" | tr -d h | tr -d e | tr -d o
ll

我正在尝试找到一种方法,将每个命令的输出显示到一个衬里内的屏幕上,以便其他运行它的人可以看到发生了什么。继续上面的示例,我希望输出如下;

$ echo "hello" | tr -d h | tr -d e | tr -d o
hello
ello
llo
ll

这可能吗?根据上述单线的操作,我们使用垂直管道将命令的输出传送到命令。所以我假设我必须从管道中断打印到标准输出,然后会中断我编写的“命令链”。或者也许tee可以在这里使用,但我似乎无法达到愿望效果。 更新tee不起作用,因为它的输出仍在管道的边界内,呵呵!

非常感谢。

4

8 回答 8

6

这仅适用于终端:

echo hello  | tee /dev/tty |
    tr -d h | tee /dev/tty |
    tr -d e | tee /dev/tty |
    tr -d o

/dev/tty无论正常输出到哪里,设备都会将输出重定向到当前终端。

于 2012-06-09T13:12:31.690 回答
4

您可以tee直接输出到终端:

echo hello  | tee /proc/$$/fd/1 |
    tr -d h | tee /proc/$$/fd/1 |
    tr -d e | tee /proc/$$/fd/1 |
    tr -d o

$$是外壳的 PID。

于 2012-06-09T13:12:59.800 回答
3

IMO,如果这是现实世界的问题,而不是如何在 bash 中进行操作,那么您可以尝试一个简单的 perl oneliner,而不是启动 X tr 和 Y tee 进程的 bash 疯狂:

echo hello | perl -nale 'foreach $i (qw(h e o)) {@F=map{s/$i//g;print $_;$_}@F}'

将打印:

ello
llo
ll

或者如果你真的想要 bash(正如@chepner 建议的那样)

echo "hello" | while read w; do for c in h e o; do w=${w//$c};echo $w; done;done

或者

while read w; do for c in h e o; do w=${w//$c};echo $w; done;done < wordlist
于 2012-06-09T14:14:36.837 回答
2

有一个小循环:

w="hello" ; for c in h e o .; do echo $w; w=$(echo $w | tr -d $c); done

这 。仅用于简要解决方案。在更仔细地阅读了这个问题之后,我测试并发现它也可以在管道链中工作:

w="hello" ; for c in h e o .; do echo $w; w=$(echo $w | tr -d $c); done | less 
# pure bash buildins, see chepner's comment
w="hello" ; for c in h e o .; do echo $w; w=${w/$c}; done
于 2012-06-09T12:56:02.103 回答
0

您可以使用tee -as-代表控制台:

echo "hello" | tee - | tr -d h | tee - | tr -d e | tee - | tr -d o

希望有帮助!

编辑

该解决方案将不起作用,因为stdout所有通过stdout.

我不会删除答案,因为它明确指出它不能解决问题,但也表明这种解决方案无效以及原因。如果有人发现自己处于相同的情况,就会发现此信息,这将很有用。

于 2012-06-09T12:28:28.717 回答
0

但这起作用:

tmp=`echo "hello"`; echo $tmp; tmp=`echo $tmp | tr -d h`; echo $tmp; tmp=`echo $tmp | tr -d e`; echo $tmp; echo $C | tr -d o

这很丑陋,但它有效。该解决方案创建变量来存储每个传递,然后将它们全部显示:

tmp=`echo "hello"`
echo $tmp
tmp=`echo $tmp | tr -d h`
echo $tmp
tmp=`echo $tmp | tr -d e`
echo $tmp
echo $C | tr -d o

我找不到更好的解决方案。

于 2012-06-09T12:48:53.027 回答
0

您可以使用您收听的 fifo(或常规文件)来执行此操作:

mkfifo tmp.fifo
tail -f tmp.fifo

然后只需在单独的 shell 上运行您的命令:

echo hello | tee -a tmp.fifo | tr -d e | tee -a tmp.fifo | tr -d o
于 2012-06-09T12:51:43.947 回答
0

再住一间?

echo "hello" | tee >(tr -d h | tee >(tr -d e | tee >(tr -d o) ) )

或者

 echo "hello" | 
tee >(tr -d h | 
tee >(tr -d e | 
tee >(tr -d o  ) ) ) 

输出是:

hello
ubuntu@ubuntu:~$ ello
llo
ll

消除腐败需要一点有说服力的强制手段ubuntu@ubuntu:~$

cat <(echo "hello" | tee >(tr -d h | tee >(tr -d e | tee >(tr -d o) ) ) )

输出是:

hello
ello
llo
ll
于 2013-03-08T05:49:11.680 回答