linux - 可选从标准输入或文件读取的 bash 标志
问题描述
我知道这可能是一个愚蠢的问题,但它让我难住了。我正在尝试编写一个接受标志和一个可选变量的 shell 脚本。一份文件。如果传递了一个文件,它将从该文件中读取。如果不是,它从标准输入读取。我知道有人问过类似的问题,但我找不到我的具体问题的答案。
我在下面提供了一个示例来说明该问题。为简洁起见,我省略了一些部分(例如验证)。
我可以接受标志并从文件中读取。或者我可以选择接受一个变量(文件)并从文件中读取。如果没有文件传递,那么我们从标准输入读取。出于某种原因,当我尝试将两者结合起来(接受标志,读取默认为标准输入的可选文件)时,出现错误。
这行得通。
#!/bin/sh
set -eu
while IFS=, read -r f1
do
echo $f1
done <"${1:-/dev/stdin}"
我可以这样称呼它……./test.sh <<< "testing123"
或者这样……echo "testing123" | ./test.sh
或者这样…… ./test.sh foo.csv
。testing123
假设 foo.csv 包含所有返回testing123
。
这也有效。
#!/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}"
我可以这样./test.sh foo.csv
或这样称呼它./test.sh -f foo.csv
。第一种情况返回testing123
,第二种情况返回
unknown
testing123
出于某种原因,这不起作用。我不明白我在这里错过了什么?
#!/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}"
像这样调用./test foo.csv
它返回testing123
。像这样调用./test -f foo.csv
它返回
unknown
testing123
像这样调用:
echo "testing123" | ./test.sh
或这个
./test.sh <<< "testing123"
它返回
./test.sh: line 6: $1 unbound variable
解决方案
改变
while true
至
while [ $# -ne 0 ]
当您用完参数时,您的代码将继续循环的下一次迭代,并尝试测试$1
不存在的。由于您已经完成set -eu
,引用未设置的变量会导致错误并且脚本中止。
推荐阅读
- r - 是否有可能在 R 中创建概率定律?
- reactjs - React TypeScript:轮播:每 3 秒旋转一次图像
- python - 如何从字典中删除nan键?
- javascript - Angular Slickgrid-如何使用上下文菜单中选择的选项更新或替换特定的单元格值
- laravel - 显示一个数组,但它返回空
- python - 在python中组合json字符串时出现语法错误
- java - 在 Java 中运行稳定婚姻算法时难以读取 .txt 数据
- javascript - 当我使用 CSS 将鼠标悬停在按钮上时,我试图让按钮中的文本改变颜色
- regex - 如何使用以下文本中的正则表达式获取发票编号和客户采购订单?
- android - 从 recyclerView 项目到另一个活动的 recyclerView 项目的共享元素转换?