如果没有文件,则从stdin读取linux shell脚本



我正试图将我的Linux shell脚本设置为从文件读取(我正在处理),但如果没有任何文件,那么我需要从stdin读取。

读取文件的命令如下所示:

./stats -row test_file

我如何才能用这样的东西读取用户输入的内容:

./stats -row 4 2 3 5 3 4 5 3 6 5 6 3 4

当我输入这样的命令时,我会得到"没有这样的文件或目录"

我把剧本分解成我需要帮助的问题。

#!/bin/sh
INPUT_FILE=$2         #Argument 2 from command line is the input file
exec 5< $INPUT_FILE   #assign input file to file descriptor #5
while read -u 5 line  #read from file descriptor 5 (input file)
do
    echo "$line"
done
exec 5<&-   #close file descriptor #5

这也不适用于我需要的输入。

while read line  
do
    echo "$line"
done <$2

InArtful解决方案

一个非常巧妙的if语句就可以做到这一点:

INPUT_FILE=$2         #Argument 2 from command line is the input file
if [ -f "$INPUT_FILE" ]; then
    while read -r line
    do
        echo "$line"
    done <"$INPUT_FILE"
else
    while read -r line
    do
        echo "$line"
    done
fi

注意:这假设您仍在寻找文件名作为第二个参数。


巧妙的解决方案

我不能相信,但artful解决方案已经在这里得到了答案:如何在bash中读取文件或stdin

INPUT_FILE=${2:-/dev/stdin}         #Argument 2 from command line is the input file
while read -r line
do
    echo "$line"
done <"$INPUT_FILE"
exit 0

我一直在寻找这样的解决方案,但错过了stdin设备/dev/stdin作为INPUT_FILES的默认设备注意此解决方案仅限于具有proc文件系统的操作系统。

在bash脚本中,我通常将从文件(或管道)读取的代码放在函数中,其中重定向可以与逻辑分离。

此外,当从文件或STDIN读取时,逻辑最好不要关心哪个是哪个。因此,最好将STDIN捕获到一个临时文件中,然后读取代码的文件的其余部分是相同的。

下面是一个从ARG1或STDIN读取的示例脚本,它只计算文件中的行数。它还对同一输入调用wc -l,并显示两个方法的结果。

#!/bin/bash
# default input is this script
input=$0
# If arg given, read from it
if (( $# > 0 )); then
  input=$1
  echo 1>&2 "Reading from $input"
else
  # otherwise, read from STDIN
  # since we're reading twice, need to capture it into
  # a temp file
  input=/tmp/$$.tmp
  cat >$input
  trap "rm -f $input" EXIT ERR HUP INT QUIT
  echo 1>&2 "Reading from STDIN (saved to $input)"
fi
count_lines() {
  local count=0
  while read line ; do
    let count+=1
  done
  echo $count
}
lines1=`count_lines <$input`
lines2=`wc -l <$input`
fmt="%15s: %dn"
printf "$fmt" 'count_lines' $lines1
printf "$fmt" 'wc -l'       $lines2
exit

这里有两个调用:一个带有arg1上的文件,另一个没有参数,从STDIN:读取

$ ./t2.sh t2.sh
Reading from t2.sh
    count_lines: 35
          wc -l: 35
$ ./t2.sh <t2.sh
Reading from STDIN (saved to /tmp/8757.tmp)
    count_lines: 35
          wc -l: 35

最新更新