Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何在shell脚本中将文件作为stdin传递_Linux_Bash_Shell - Fatal编程技术网

Linux 如何在shell脚本中将文件作为stdin传递

Linux 如何在shell脚本中将文件作为stdin传递,linux,bash,shell,Linux,Bash,Shell,我有一个bash脚本,在这样调用时可以工作:/stats.sh-rows test\u文件 该程序主要计算行平均值和中间值&列平均值和中间值。现在我想把文件作为标准输入传递给程序。但是当我运行这段代码时,它会打印出“您有2个参数提供2个参数”。我应该做哪些更改,以便代码将stdin作为文件。我的意思是说,如果我想运行脚本,我也可以通过这种方式运行它/stats.sh-rows&2 出口1 elif[“$#”-gt 2];然后 回声“${#}” FILE=“${4}” 如果[-f“${FILE}”

我有一个bash脚本,在这样调用时可以工作:
/stats.sh-rows test\u文件

该程序主要计算行平均值和中间值&列平均值和中间值。现在我想把文件作为标准输入传递给程序。但是当我运行这段代码时,它会打印出
“您有2个参数提供2个参数”
。我应该做哪些更改,以便代码将stdin作为文件。我的意思是说,如果我想运行脚本,我也可以通过这种方式运行它
/stats.sh-rows
。我想得到这个功能

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

我编写的代码如下:

#! /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
#/bin/bash
清楚的
#下面的参数将检查您是否正确提供了命令行参数
标志=0
如果[“$#”-等式0];然后
echo“请提供参数”
elif[“$#”—lt 2];然后
echo“您必须提供2个参数”>&2
出口1
elif[“$#”-gt 2];然后
回声“${#}”
FILE=“${4}”
如果[-f“${FILE}”];然后
标志=1
其他的
echo“您提供了更多参数”>&2
fi
出口1
其他的
echo“您输入了正确数量的参数”
fi
#下面的代码是用于检查是否有-r/-rows或-c/-cols的案例代码
option=“${1}”
l1=0
排序=()
中的案例${option}
-行|-r |-r*)
如果[$flag-等式1];然后
FILE=“${4}”
其他的
FILE=“${2}”
fi
清楚的
回声“平均中值”
行=$(wc-l<“$文件”)
而read-r行
做
len=0
tot=0
name=$line
#数组=(`echo$name | cut-d”“--输出分隔符=”“-f1-`)

IFS=''read-a数组使用
reada
insight您的bash脚本来读取/处理stdin的内容

例如:

skcript.sh:

read a
echo "content of std in"
echo a

在这种情况下,
cat test_file.txt | stats.sh
将起作用。

您也可以在脚本中将文件重定向到stdin:

# redirect FILE to stdin
exec 0<$FILE
# read from FILE
read VAR
#将文件重定向到stdin

exec 0在许多现代体系结构上,如果脚本绝对要求您传递文件名参数,则可以传递
/dev/stdin
以使标准输入作为类似文件名的实体可用。许多脚本也接受
-
作为一个特殊的文件名,意思是“不要打开文件,而是读取标准输入”。类似于
/stats.sh-rows的东西-我不是bash/shell高手,但你不能只使用
cat file.txt | stats.sh
?@Al.G。这显然是很理想的,但是脚本是专门为防止这种情况而设计的。谢谢你的回答和建议。我实际上使用python来实现这一点,但我正在学习bash,所以我只是用bash编写了它
# redirect FILE to stdin
exec 0<$FILE
# read from FILE
read VAR