来自管道的Bash输入

3
我写了一个简单的bash脚本,可以从文件或标准输入中随机输出一行:
#!/bin/bash
if [ $# -ne 1 ]
then
    echo "Syntax: $0 FILE (or \'-\' for STDIN)"
    echo $0 - display a random line from FILE
    exit 1
fi

RAND=`cat /proc/sys/kernel/random/uuid | cut -c1-4 | od -d | head -1 | cut -d' ' -f2`

if [ $1 != "-" ]
then
    LINES=`cat "$1" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    head -$LINE $1 | tail -1
else
    piped=`cat -`
    LINES=`echo "$piped" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    echo "$piped" | head -$LINE | tail -1
fi

然而,如果没有传递参数,我希望它也能处理标准输入(如果没有来自管道的标准输入,则仍然会失败并显示帮助信息)。

也就是说,我想要实现:

echo "foo\nbar\nbaz" | randline

使用...代替...

echo "foo\n\bar\nbaz" | randline -

如何实现这个呢?
编辑: 感谢Doon!
#!/bin/bash
if [ "$( tty )" == 'not a tty' ]
then
    STDIN_DATA_PRESENT=1
else
    STDIN_DATA_PRESENT=0
fi

if [[ $# -ne 1 && $STDIN_DATA_PRESENT -eq 0 ]]
then
    echo "Syntax: $0 [FILE (or \'-\' for STDIN)]"
    echo $0 - display a random line from FILE
    echo -e "\nWill also process piped STDIN if no arguments are given."
    exit 1
fi

RAND=`cat /proc/sys/kernel/random/uuid | cut -c1-4 | od -d | head -1 | cut -d' ' -f2`

if [[ $1 && $1 != "-" ]]
then
    LINES=`cat "$1" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    head -$LINE $1 | tail -1
else
    piped=`cat -`
    LINES=`echo "$piped" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    echo "$piped" | head -$LINE | tail -1
fi

1
请看这里https://dev59.com/oEbRa4cB1Zd3GeqP4Nia,它是针对ksh的,但提供了bash的答案。 - Doon
1
你应该从问题中删除解决方案,并将其作为答案添加(如果它确实解决了你的问题,则接受它)。 - murgatroid99
2个回答

2
要从文件中获取随机行,您可以执行以下操作:
awk 'BEGIN{srand();}{printf "%04d %s\n", int(rand()*10000), $0}' < $FILENAME | sort | cut -f2- -d' ' | head -1

这里我们需要做以下操作:

  1. 在每行开头添加随机数字
  2. 对输出进行排序
  3. 移除每行开头的随机数字
  4. 打印混合输出的第一行

顺便提一下,如果你使用BASH,可以使用由BASH提供的$RANDOM变量代替手动生成的$RAND。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接