如何在 Bash 脚本中检查是否未提供命令行参数或 STDIN?
我的意思是如果我跑:
#> ./myscript.sh
... Show message "No data provided..." and exit
或者:
#> ./myscript.sh filename.txt
... Read from filename.txt
或者:
#> ./myscript.sh < filename.txt**
... Read from STDIN
答案1
这符合您的要求吗?
#!/bin/sh
if test -n "$1"; then
echo "Read from $1";
elif test ! -t 0; then
echo "Read from stdin"
else
echo "No data provided..."
fi
主要技巧如下:
检测是否有参数是通过
test -n $1
检查第一个参数是否存在来完成的。然后,检查
stdin
终端上是否未打开(因为它通过管道传输到文件)test ! -t 0
(检查文件描述符零(又名stdin
)是否未打开)。最后,其他所有情况都属于最后一种情况 (
No data provided...
)。
答案2
我四处寻找却无果,最后经过反复尝试终于成功将其整合在一起。自此以后,它已在众多用例中完美地发挥作用。
#!/bin/bash
### LayinPipe.sh
## Recreate "${@}" as "${Args[@]}"; appending piped input.
## Offers usable positional parameters regardless of where the input came from.
##
## You could choose to create the array with "${@}" instead following
## any piped arguments by simply swapping the order
## of the following two 'if' statements.
# First, check for normal positional parameters.
if [[ ${@} ]]; then
while read line; do
Args[${#Args[@]}]="${line}"
done < <(printf '%s\n' "${@}")
fi
# Then, check for piped input.
if [[ ! -t 0 ]]; then
while read line; do
Args[${#Args[@]}]="${line}"
done < <(cat -)
fi
# Behold the glory.
for ((a=0;a<${#Args[@]};a++)); do
echo "${a}: ${Args[a]}"
done
- 示例:(充分了解不鼓励使用“ls”的输出作为输入,以显示此解决方案的灵活性。)
$ ls
: TestFile.txt 'Filename with spaces'
$ ls -1 | LayinPipe.sh "$(ls -1)"
> 0: Filename with spaces
> 1: TestFile.txt
> 2: Filename with spaces
> 3: TestFile.txt
$ LayinPipe.sh "$(ls -1)"
> 0: Filename with spaces
> 1: TestFile.txt
$ ls -1 | LayinPipe.sh
> 0: Filename with spaces
> 1: TestFile.txt
答案3
[已解决] 在 bash shell 中...
... read -t 0 :参见“帮助阅读”
$ function read_if_stdin_not_empty {
if read -t 0 ; then
while read ; do
echo "stdin receive : $REPLY"
read_if_stdin_not_empty
done
else
echo "stdin is empty .."
fi
}
# TESTs:
$ read_if_stdin_not_empty
stdin is empty ..
$ echo '123' | read_if_stdin_not_empty
stdin receive : 123
$s='123
456'
$ echo "$s" | read_if_stdin_not_empty
stdin receive : 123
stdin receive : 456
答案4
我提出了一个综合了之前非常有趣的答案的函数:
文件test.sh:
#!/bin/bash
function init_STDIN() {
## Version 1.0.0
## Creates the global variable array indexed STDIN
## which contains the possible lines sent in the
## file descriptor /dev/stdin of the script
declare -ga STDIN
read -t0 || return 1
while read LINE; do
STDIN[${#STDIN[@]}]="$LINE"
done < <(cat -)
test ${#STDIN[@]} -ne 0
}
if init_STDIN; then
echo "Feed provided on /dev/stdin. Processing..."
echo "For this example, /dev/stdin is:"
for ((I=0; I<${#STDIN[@]}; I++)); do
echo ${STDIN[$I]}
done
else
echo "Working without any feed on /dev/stdin..."
fi
echo
echo "For this example, the ${#@} parameter(s) provided on the command line is(are) :"
echo $@
测试:
$ ./test.sh some args ...
Working without any feed on /dev/stdin...
For this example, the 3 parameter(s) provided on the command line is(are) :
some args ...
$ seq 1 10 | sed 's/ /\n/g' | ./test.sh some args ...
Feed provided on /dev/stdin. Processing...
For this example, /dev/stdin is:
1
2
3
4
5
6
7
8
9
10
For this example, the 3 parameter(s) provided on the command line is(are) :
some args ...
$ seq 1 10 | sed 's/ /\n/g' | (exec 0<&-; ./test.sh some args ...)
Working without any feed on /dev/stdin...
For this example, the 3 parameter(s) provided on the command line is(are) :
some args ...