linux - 如何在 shell 脚本中将文件作为标准输入传递

标签 linux bash shell

我有一个 bash 脚本,它可以像这样调用:./stats.sh -rows test_file

该程序主要计算行平均值和中位数以及列平均值和中位数。现在我想将文件作为标准输入传递给程序。但是当我运行这段代码时,它会打印出 "you have 2 provide 2 arguments" .我必须进行哪些更改才能使代码将标准输入作为文件。我的意思是说,如果我想运行脚本,我也可以通过这种方式运行它 ./stats.sh -rows < test_file .我想获得这个功能!!

输入文件是:(由制表符分隔的列)

93  93  93  93  93  93  93  93  100
73  84  95  83  72  86  80  97  100
85  0   82  75  88  79  80  81  100
85  0   87  73  88  79  80  71  100
80  81  83  63  100 85  63  68  100
53  57  61  53  70  61  73  50  100
55  54  41  63  63  45  33  41  100
53  55  43  44  63  75  35  21  100
100 100 100 100 100 100 100 100 100

我处理的代码是这样的:

#! /bin/bash
clear
#the arguments below will check for your command line args whether you have provided corrctly or not
flag=0
if [ "$#" -eq 0 ]; then
    echo "Please provide arguments"
elif [ "$#" -lt 2 ]; then
     echo "You have to provide 2 arguments" >&2
     exit 1
elif [ "$#" -gt 2 ]; then
    echo "${#}"
    FILE= "${4}"
    if [ -f "${FILE}" ]; then
     flag=1
    else
      echo "You have provided more number of arguments" >&2
    fi
    exit 1
else
    echo "You have entered correct number of arguments"
fi
# the below code is the case code which checks whether you have -r/-rows or -c/-cols
option="${1}"
l1=0
sorted=()
case ${option} in 
   -rows| -r| -r*)
      if [ $flag -eq 1 ]; then
        FILE="${4}"
      else
        FILE="${2}"
      fi
      clear
      echo "Average  Median"
      lines=$(wc -l < "$FILE")
      while read -r line
      do
      len=0
      tot=0
      name=$line
      #array=(`echo $name | cut -d "    "  --output-delimiter=" " -f 1-`)
      IFS=' ' read -a array <<< "$name"  #if any error comes that might be with this line just check the spaces in the speech marks they should be 4 spaces as it is checking for tabs
      for element in "${array[@]}"
      do
          tot=$(expr $tot + $element)
          #let tot+=$element #you can use this as well to get the totals
          let len+=1
      done
      avg=($(printf "%.0f" $(echo "scale=2;$tot/$len" | bc)))
      readarray -t sorted < <(for a in "${array[@]}"; do echo "$a"; done | sort)
      no=`expr $len % 2`
      if [ $no -eq 0 ]; then
      mid=`expr $len / 2`
      echo "$avg   ${sorted[$mid]}"
      else
      if [ $lines -lt 2 ]; then
        mid=`expr $len / 2`
            echo "$avg   ${sorted[$mid]}"
      else
        l1=`expr $len / 2`
        mid=`expr $l1 + 1`
        echo "$avg   ${sorted[$mid]}"
      fi

      fi
      unset "array[@]"
      unset "sorted[@]"
      done < "$FILE"
      ;;

   -cols| -c| -c*)
      if [ $flag -eq 1 ]; then
        FILE="${4}"
      else
        FILE="${2}"
      fi
      #echo "cols"
      #echo "File name is $FILE"
      cols=$(head -1 "$FILE" | tr "\t" '\n' | wc -l)
      lines=$(wc -l < "$FILE")
      IFS=$'\t\n' read -d '' -r -a lins < "$FILE"
      while read line;do
      x=1
      read -a array <<< "$line" ##Split the line by spaces
      for element in "${!array[@]}"
      do
      row[${element}]=$((${row[${element}]}+${array[$element]})) ##For each column increment array variable by number in the column.
      ((x++))
      done
      done < "$FILE"
      echo "Averages: "
      for element in ${row[@]}
      do
      mean= printf "%.0f" $(echo "scale=2;$element/$lines" | bc) ##bc prints floating point numbers and then we round of using scale and .0f
      echo -n "$mean    "
      done
      printf "\n"
      echo "Medians: "
      for ((i=0;i<$cols;i++))
      do 
      carr=()
      for ((j=i;j<$lines * $cols;j=j+$cols)) 
      do
          carr+=(${lins[$j]})
      done
    IFS=$' \n' csort=($(sort <<<"${carr[*]}"))
    no=`expr $lines % 2`
    if [ $no -eq 0 ]; then
           mid=`expr $lines / 2`
           echo -n "${csort[$mid]}    "
    else
           if [ $lines -lt 2 ]; then
                  mid=`expr $lines / 2`
              echo -n "${csort[$mid]}    "
           else
              l1=`expr $lines / 2`
              mid=`expr $l1 + 1`
              echo -n "${csort[$mid]}    "
           fi
    fi
      done <<<"$lins"
      printf "\n"

      ;; 
   *)  
      echo "`basename ${0}`:usage: [-r|-rows rows] | [-c|-cols columns]" 
      exit 1 # Command to come out of the program with status 1
      ;; 
esac 
trap "echo ;exit" 1 2

最佳答案

您还可以在脚本中将文件重定向到标准输入:

# redirect FILE to stdin
exec 0<$FILE
# read from FILE
read VAR

关于linux - 如何在 shell 脚本中将文件作为标准输入传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29695444/

相关文章:

c - 为什么 rand() 在 Linux 上比 Mac 更频繁地重复数字?

bash - 使用 shell 脚本删除除每行第一个以外的所有逗号

bash - 我已经重定向了 stdout 和 stderr,为什么我仍然得到一些输出?

java - 调用 Java Swing 程序的最佳实践

bash - 为什么要在 .profile 脚本中转义 eval 的第一个字符?

linux - 脚本的crontab

linux - 创建 Linux Pidfile

linux - 如何在 Linux 中存储不同编译的相同库版本?

c++ - 通过 shell 脚本和 C++ 获取当前前台应用程序的名称

bash - 在上一个命令失败后创建带有红色 $ 的 Bash 命令提示符