Tôi cần kiểm tra sự tồn tại của một đối số đầu vào. Tôi có đoạn script sau
if [ "$1" -gt "-1" ]
then echo hi
fi
tôi có
[: : integer expression expected
Làm cách nào để kiểm tra đối số đầu vào1 trước để xem nó có tồn tại không?
Tôi cần kiểm tra sự tồn tại của một đối số đầu vào. Tôi có đoạn script sau
if [ "$1" -gt "-1" ]
then echo hi
fi
tôi có
[: : integer expression expected
Làm cách nào để kiểm tra đối số đầu vào1 trước để xem nó có tồn tại không?
Câu trả lời:
Nó là:
if [ $# -eq 0 ]
then
echo "No arguments supplied"
fi
Các $#
biến sẽ cho bạn biết số lượng các đối số đầu vào kịch bản đã được thông qua.
Hoặc bạn có thể kiểm tra xem một đối số có phải là một chuỗi rỗng hay không như sau:
if [ -z "$1" ]
then
echo "No argument supplied"
fi
Công -z
tắc sẽ kiểm tra xem việc mở rộng "$ 1" có phải là chuỗi null hay không. Nếu nó là một chuỗi null thì phần thân được thực thi.
exit 1
phần cuối của tiếng vang bên trong khối if khi đối số được yêu cầu để tập lệnh hoạt động. Rõ ràng, nhưng đáng chú ý cho sự đầy đủ.
programname "" secondarg third
. Các $#
kiểm tra một cách rõ ràng để kiểm tra số lượng các đối số.
if [ ! -z "$1" ]; then ...
Tốt hơn là chứng minh theo cách này
if [[ $# -eq 0 ]] ; then
echo 'some message'
exit 1
fi
Bạn thường cần phải thoát nếu bạn có quá ít đối số.
exit 1
thứ bạn thường muốn và sử dụng [[ ]]
thử nghiệm mà (iirc) thường hợp lý hơn. Vì vậy, đối với những người mù dán mã sao chép thì đây là câu trả lời tốt hơn.
Trong một số trường hợp, bạn cần kiểm tra xem người dùng có chuyển đối số cho tập lệnh hay không và nếu không, hãy quay lại giá trị mặc định. Giống như trong kịch bản dưới đây:
scale=${2:-1}
emulator @$1 -scale $scale
Ở đây nếu người dùng không vượt qua scale
như một tham số thứ 2, tôi sẽ khởi chạy trình giả lập Android -scale 1
theo mặc định. ${varname:-word}
là một toán tử mở rộng. Ngoài ra còn có các toán tử mở rộng khác:
${varname:=word}
trong đó thiết lập không xác định varname
thay vì trả về word
giá trị;${varname:?message}
sẽ trả về varname
nếu nó được xác định và không rỗng hoặc in message
và hủy bỏ tập lệnh (như ví dụ đầu tiên);${varname:+word}
word
chỉ trả về nếu varname
được định nghĩa và không null; trả về null nếu không.${varname?message}
. Là thêm :
một lỗi đánh máy, hoặc nó thay đổi hành vi?
: ${1?"First argument is null"} ${2?"Please provide more than 1 argument"}
Thử:
#!/bin/bash
if [ "$#" -eq "0" ]
then
echo "No arguments supplied"
else
echo "Hello world"
fi
$#
và 0
?
else
, quá.
foo*
) và tách từ (nghĩa là chia nội dung nếu giá trị chứa khoảng trắng). Trong trường hợp này, không cần thiết phải trích dẫn $#
vì cả hai trường hợp này đều không áp dụng. Trích dẫn 0
cũng không cần thiết, nhưng một số người thích trích dẫn các giá trị vì chúng thực sự là chuỗi và điều đó làm cho nó rõ ràng hơn.
Một cách khác để phát hiện nếu các đối số được truyền vào tập lệnh:
((!$#)) && echo No arguments supplied!
Lưu ý rằng (( expr ))
làm cho biểu thức được đánh giá theo quy tắc của Số học Shell .
Để thoát trong trường hợp không có bất kỳ đối số, người ta có thể nói:
((!$#)) && echo No arguments supplied! && exit 1
Một cách khác (tương tự) để nói ở trên sẽ là:
let $# || echo No arguments supplied
let $# || { echo No arguments supplied; exit 1; } # Exit if no arguments!
help let
nói:
let: let arg [arg ...]
Evaluate arithmetic expressions. ... Exit Status: If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.
exit
giết chết quá trình zsh của tôi, tôi sử dụng return
nó không giết nó
((!$#))
kích hoạt lịch sử thay thế?
Chỉ vì có thêm một điểm cơ bản để chỉ ra tôi sẽ thêm rằng bạn chỉ có thể kiểm tra chuỗi của mình là null:
if [ "$1" ]; then
echo yes
else
echo no
fi
Tương tự như vậy nếu bạn đang mong đợi số lượng arg chỉ cần kiểm tra lần cuối của bạn:
if [ "$3" ]; then
echo has args correct or not
else
echo fixme
fi
và như vậy với bất kỳ arg hoặc var
Nếu bạn muốn kiểm tra xem đối số có tồn tại hay không, bạn có thể kiểm tra xem # của đối số lớn hơn hoặc bằng số đối số mục tiêu của bạn.
Kịch bản sau đây cho thấy cách thức hoạt động của nó
#!/usr/bin/env bash
if [ $# -ge 3 ]
then
echo script has at least 3 arguments
fi
tạo ra đầu ra sau
$ ./test.sh
~
$ ./test.sh 1
~
$ ./test.sh 1 2
~
$ ./test.sh 1 2 3
script has at least 3 arguments
$ ./test.sh 1 2 3 4
script has at least 3 arguments
Như một lời nhắc nhở nhỏ, các nhà khai thác thử nghiệm số trong Bash chỉ làm việc trên các số nguyên ( -eq
, -lt
, -ge
, vv)
Tôi muốn đảm bảo $ vars của tôi là ints
var=$(( var + 0 ))
trước khi tôi kiểm tra chúng, chỉ cần bảo vệ chống lại lỗi "[: số nguyên arg yêu cầu".
var=$(printf "%.0f" "$var")
có thể xử lý số float nhưng bị thoát khỏi số 0 khi được cung cấp một chuỗi. Nếu bạn không phiền một awk, phương pháp này tôi sử dụng dường như là mạnh mẽ nhất để thực thi một số nguyên : var=$(<<<"$var" awk '{printf "%.0f", $0}')
. Nếu var không được đặt, nó mặc định là "0". Nếu var là float, nó được làm tròn đến số nguyên gần nhất. Giá trị tiêu cực cũng tốt để sử dụng.
xác nhận chức năng bash liner
myFunction() {
: ${1?"forgot to supply an argument"}
if [ "$1" -gt "-1" ]; then
echo hi
fi
}
thêm tên hàm và cách sử dụng
myFunction() {
: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"}
if [ "$1" -gt "-1" ]; then
echo hi
fi
}
thêm xác nhận để kiểm tra nếu số nguyên
để thêm xác thực bổ sung, ví dụ để kiểm tra xem đối số được truyền có phải là số nguyên hay không, hãy sửa đổi một lớp xác thực để gọi hàm xác thực:
: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"} && validateIntegers $1 || die "Must supply an integer!"
sau đó, xây dựng hàm xác thực để xác thực đối số, trả về 0 khi thành công, 1 khi thất bại và hàm chết hủy bỏ tập lệnh khi thất bại
validateIntegers() {
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
return 1 # failure
fi
return 0 #success
}
die() { echo "$*" 1>&2 ; exit 1; }
Thậm chí đơn giản hơn - chỉ cần sử dụng set -u
set -u
đảm bảo rằng mọi biến được tham chiếu được đặt khi nó được sử dụng, vì vậy chỉ cần đặt nó và quên nó
myFunction() {
set -u
if [ "$1" -gt "-1" ]; then
echo hi
fi
}
[ -z "$1" ] && echo "No argument supplied"
Tôi thích một lớp lót, vì chúng dễ dàng hơn cho tôi; và cũng nhanh hơn để kiểm tra giá trị thoát, so với việc sử dụngif