简体   繁体   English

bash标志,可选从stdin或文件中读取

[英]bash flags with optional read from stdin or file

I know this is probably a stupid question but it has me stumped. 我知道这可能是一个愚蠢的问题,但这使我感到困惑。 I'm trying to write a shell script that accepts flags, and one optional variable. 我正在尝试编写一个接受标志和一个可选变量的shell脚本。 A file. 一份文件。 If a file is passed, it reads from the file. 如果文件通过,它将从文件中读取。 If not, It reads from stdin. 如果不是,则从stdin读取。 I know similar questions have been asked, but I can't find an answer to my specific question. 我知道有人问过类似的问题,但我找不到特定问题的答案。

I've provided an example below that illustrates the issue. 我在下面提供了一个说明问题的示例。 I've left some parts out (such as validation) for brevity's sake. 为了简洁起见,我省略了一些部分(例如验证)。

I can accept flags and read from a file. 我可以接受标志并从文件中读取。 OR I can optionally accept a variable (file) and read from the file. 或者,我可以选择接受变量(文件)并从文件中读取。 If no file is passed, then we read from stdin. 如果没有文件通过,那么我们从标准输入中读取。 For some reason, when I try to combine the two (accept flags, read optional file defaulting to stdin) I get an error. 出于某种原因,当我尝试将两者结合在一起(接受标志,读取默认为stdin的可选文件)时,出现错误。

This works. 这可行。

#!/bin/sh
set -eu

while IFS=, read -r f1 
do
  echo $f1
done <"${1:-/dev/stdin}"

I can call it like this... ./test.sh <<< "testing123" or this... echo "testing123" | ./test.sh 我可以这样称呼它... ./test.sh <<< "testing123"或这个... echo "testing123" | ./test.sh echo "testing123" | ./test.sh or this... ./test.sh foo.csv . echo "testing123" | ./test.sh或这个... ./test.sh foo.csv All return testing123 assuming that foo.csv contains testing123 . 所有的回报testing123假设foo.csv包含testing123

This Also Works. 这也可以。

#!/bin/sh
set -eu

while true
do
  case $1 in
    -h|--help)
      echo "-h"
      exit
      ;;
    --)
      shift
      break
      ;;
    -?*)
      echo "unknown"
      ;;
    *)
      break
  esac

  shift
done

while IFS=, read -r f1 
do
  echo $f1
done <"${1}"

I can call it like this ./test.sh foo.csv or this ./test.sh -f foo.csv . 我可以这样称呼它./test.sh foo.csv或这个./test.sh -f foo.csv The first case returns testing123 and the second case returns 第一种情况返回testing123 ,第二种情况返回

unknown
testing123

For some reason, this doesn't work. 由于某种原因,这不起作用。 I don't understand what I'm missing here? 我不明白我在这里想念的是什么?

#!/bin/sh
set -eu

while true
do
  case $1 in
    -h|--help)
      echo "-h"
      exit
      ;;
    --)
      shift
      break
      ;;
    -?*)
      echo "unknown"
      ;;
    *)
      break
  esac

  shift
done

while IFS=, read -r f1 
do
  echo $f1
done <"${1:-/dev/stdin}"

Called like this ./test foo.csv it returns testing123 . 像这样./test foo.csv调用,它将返回testing123 Called like this ./test -f foo.csv it returns 这样调用./test -f foo.csv它返回

unknown
testing123

Called like this: 这样称呼:

echo "testing123" | ./test.sh

or this 或这个

./test.sh <<< "testing123"

it returns 它返回

./test.sh: line 6: $1 unbound variable

Change 更改

while true

to

while [ $# -ne 0 ]

When you run out of arguments, your code continues with the next iteration of the loop, and tries to test $1 , which doesn't exist. 当参数用完时,代码将继续循环的下一个迭代,并尝试测试$1 ,该值不存在。 Since you have done set -eu , referencing an unset variable causes an error and the script aborts. 由于已完成set -eu ,因此引用一个未设置的变量将导致错误,并且脚本将中止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM