ฉันต้องการตรวจสอบการมีอยู่ของอาร์กิวเมนต์อินพุต ฉันมีสคริปต์ต่อไปนี้
if [ "$1" -gt "-1" ]
then echo hi
fi
ฉันเข้าใจ
[: : integer expression expected
ฉันจะตรวจสอบอินพุตอาร์กิวเมนต์ 1 ก่อนเพื่อดูว่ามีอยู่ได้อย่างไร?
ฉันต้องการตรวจสอบการมีอยู่ของอาร์กิวเมนต์อินพุต ฉันมีสคริปต์ต่อไปนี้
if [ "$1" -gt "-1" ]
then echo hi
fi
ฉันเข้าใจ
[: : integer expression expected
ฉันจะตรวจสอบอินพุตอาร์กิวเมนต์ 1 ก่อนเพื่อดูว่ามีอยู่ได้อย่างไร?
คำตอบ:
มันคือ:
if [ $# -eq 0 ]
then
echo "No arguments supplied"
fi
$#
ตัวแปรจะบอกจำนวนของการขัดแย้งการป้อนข้อมูลสคริปต์ถูกผ่าน
หรือคุณสามารถตรวจสอบว่าอาร์กิวเมนต์เป็นสตริงว่างหรือไม่:
if [ -z "$1" ]
then
echo "No argument supplied"
fi
-z
สวิทช์จะทดสอบว่าการขยายตัวของ "$ 1" เป็นสตริงโมฆะหรือไม่ ถ้ามันเป็นสตริงที่เป็นโมฆะร่างกายจะถูกดำเนินการ
exit 1
ในตอนท้ายของ echos ของคุณในบล็อกถ้าเมื่ออาร์กิวเมนต์ที่จำเป็นสำหรับสคริปต์ที่จะทำงาน เห็นได้ชัดว่าคุ้มค่าที่จะต้องพิจารณา
programname "" secondarg third
. การ$#
ตรวจสอบจะตรวจสอบจำนวนอาร์กิวเมนต์อย่างไม่น่าสงสัย
if [ ! -z "$1" ]; then ...
มันเป็นการดีกว่าที่จะสาธิตวิธีนี้
if [[ $# -eq 0 ]] ; then
echo 'some message'
exit 1
fi
ตามปกติคุณจะต้องออกหากคุณมีข้อโต้แย้งน้อยเกินไป
exit 1
สิ่งที่คุณต้องการและใช้การ[[ ]]
ทดสอบที่ (iirc) มักจะสมเหตุสมผลกว่า ดังนั้นสำหรับคนคัดลอกวางรหัสสุ่มสี่สุ่มห้านี่คือคำตอบที่ดีกว่า
ในบางกรณีคุณต้องตรวจสอบว่าผู้ใช้ผ่านการโต้แย้งไปยังสคริปต์และหากไม่ให้ถอยกลับไปเป็นค่าเริ่มต้น ชอบในสคริปต์ด้านล่าง:
scale=${2:-1}
emulator @$1 -scale $scale
ที่นี่หากผู้ใช้ไม่ได้ผ่านscale
เป็นพารามิเตอร์ตัวที่สองฉันจะเรียกใช้ตัวจำลอง Android ด้วย-scale 1
ค่าเริ่มต้น ${varname:-word}
เป็นผู้ประกอบการขยายตัว มีผู้ประกอบการขยายตัวอื่น ๆ เช่นกัน:
${varname:=word}
ซึ่งตั้งค่าไม่ได้กำหนดvarname
แทนการคืนword
ค่า;${varname:?message}
ซึ่งผลตอบแทนvarname
ถ้ามันถูกกำหนดและไม่เป็นโมฆะหรือพิมพ์message
และยกเลิกสคริปต์ (เช่นตัวอย่างแรก);${varname:+word}
ซึ่งจะส่งกลับword
เฉพาะเมื่อvarname
มีการกำหนดและไม่เป็นโมฆะ ส่งกลับค่า null มิฉะนั้น${varname?message}
ตัวอย่างข้างต้นดูเหมือนว่าจะใช้ เป็นตัว:
พิมพ์พิเศษหรือเปลี่ยนพฤติกรรมหรือไม่
: ${1?"First argument is null"} ${2?"Please provide more than 1 argument"}
ลอง:
#!/bin/bash
if [ "$#" -eq "0" ]
then
echo "No arguments supplied"
else
echo "Hello world"
fi
$#
และ0
?
else
เช่นกัน
foo*
) และการแยกคำ (เช่นการแยกเนื้อหาถ้าค่ามีช่องว่าง) ในกรณีนี้ไม่จำเป็นต้องอ้าง$#
เพราะทั้งสองกรณีไม่ได้ใช้ การอ้างถึง0
ยังไม่จำเป็น แต่บางคนชอบที่จะอ้างถึงค่าเพราะมันเป็นสตริงจริง ๆ และทำให้ชัดเจนยิ่งขึ้น
อีกวิธีในการตรวจสอบว่ามีการส่งอาร์กิวเมนต์ไปที่สคริปต์หรือไม่:
((!$#)) && echo No arguments supplied!
ทราบว่า(( expr ))
เป็นสาเหตุของการแสดงออกที่จะได้รับการประเมินตามกฎของเชลล์เลขคณิต
เพื่อที่จะออกในกรณีที่ไม่มีข้อโต้แย้งใด ๆ เราสามารถพูดได้:
((!$#)) && echo No arguments supplied! && exit 1
อีกวิธีหนึ่งที่คล้ายคลึงกับการพูดข้างต้นคือ:
let $# || echo No arguments supplied
let $# || { echo No arguments supplied; exit 1; } # Exit if no arguments!
help let
พูดว่า:
let: let arg [arg ...]
Evaluate arithmetic expressions. ... Exit Status: If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.
exit
ฆ่ากระบวนการ zsh ของฉันฉันใช้return
ซึ่งไม่ฆ่ามัน
((!$#))
เรียกการทดแทนประวัติ
ฉันมักจะใช้ตัวอย่างนี้สำหรับสคริปต์ง่ายๆ:
#!/bin/bash
if [ -z "$1" ]; then
echo -e "\nPlease call '$0 <argument>' to run this command!\n"
exit 1
fi
เพียงเพราะมีจุดฐานมากขึ้นที่จะชี้ให้เห็นฉันจะเพิ่มที่คุณสามารถทดสอบสตริงของคุณเป็นโมฆะ:
if [ "$1" ]; then
echo yes
else
echo no
fi
เช่นเดียวกันหากคุณคาดหวังว่า arg จะนับเพียงทดสอบครั้งสุดท้ายของคุณ:
if [ "$3" ]; then
echo has args correct or not
else
echo fixme
fi
และอื่น ๆ ด้วย arg หรือ var
หากคุณต้องการตรวจสอบว่ามีอาร์กิวเมนต์อยู่หรือไม่คุณสามารถตรวจสอบว่า # ของอาร์กิวเมนต์นั้นมากกว่าหรือเท่ากับหมายเลขอาร์กิวเมนต์เป้าหมายของคุณ
สคริปต์ต่อไปนี้แสดงให้เห็นถึงวิธีการทำงาน
#!/usr/bin/env bash
if [ $# -ge 3 ]
then
echo script has at least 3 arguments
fi
สร้างเอาต์พุตต่อไปนี้
$ ./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
เป็นตัวเตือนเล็ก ๆ ที่ผู้ประกอบการทดสอบที่เป็นตัวเลขในทุบตีเท่านั้นทำงานในจำนวนเต็ม ( -eq
, -lt
, -ge
ฯลฯ )
ฉันต้องการให้แน่ใจว่า $ vars ของฉันเป็น ints
var=$(( var + 0 ))
ก่อนที่ฉันจะทดสอบพวกเขาเพียงเพื่อป้องกันข้อผิดพลาด "[: จำเป็นต้องระบุจำนวนเต็ม ARG"
var=$(printf "%.0f" "$var")
สามารถจัดการลอย แต่ทนทุกข์ทรมานจากการออกที่ไม่เป็นศูนย์เมื่อได้รับสตริง หากคุณไม่ได้ใจ awk var=$(<<<"$var" awk '{printf "%.0f", $0}')
นี้ใช้วิธีการที่ผมน่าจะเป็นที่แข็งแกร่งที่สุดสำหรับการบังคับใช้จำนวนเต็ม: หากไม่ได้ตั้งค่า var จะมีค่าเริ่มต้นเป็น "0" ถ้า var เป็นทศนิยมมันจะถูกปัดเศษเป็นจำนวนเต็มที่ใกล้เคียงที่สุด ค่าลบก็ใช้ได้เช่นกัน
การตรวจสอบฟังก์ชั่นซับหนึ่งทุบตี
myFunction() {
: ${1?"forgot to supply an argument"}
if [ "$1" -gt "-1" ]; then
echo hi
fi
}
เพิ่มชื่อฟังก์ชั่นและการใช้งาน
myFunction() {
: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"}
if [ "$1" -gt "-1" ]; then
echo hi
fi
}
เพิ่มการตรวจสอบเพื่อตรวจสอบว่าจำนวนเต็ม
เพื่อเพิ่มการตรวจสอบเพิ่มเติมตัวอย่างเช่นการตรวจสอบเพื่อดูว่าข้อโต้แย้งที่ส่งเป็นจำนวนเต็มหรือไม่ให้แก้ไขการตรวจสอบความถูกต้องหนึ่งรายการเพื่อเรียกใช้ฟังก์ชันการตรวจสอบความถูกต้อง:
: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"} && validateIntegers $1 || die "Must supply an integer!"
จากนั้นสร้างฟังก์ชันการตรวจสอบความถูกต้องที่ตรวจสอบความถูกต้องของอาร์กิวเมนต์คืนค่า 0 เมื่อสำเร็จ, 1 เมื่อล้มเหลวและฟังก์ชันตายที่ยกเลิกสคริปต์เมื่อเกิดความล้มเหลว
validateIntegers() {
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
return 1 # failure
fi
return 0 #success
}
die() { echo "$*" 1>&2 ; exit 1; }
ง่ายกว่า - เพียงใช้ set -u
set -u
ทำให้แน่ใจว่าทุกตัวแปรที่อ้างอิงถูกตั้งค่าไว้เมื่อมีการใช้งานดังนั้นเพียงแค่ตั้งค่าและลืมมันไป
myFunction() {
set -u
if [ "$1" -gt "-1" ]; then
echo hi
fi
}
[ -z "$1" ] && echo "No argument supplied"
ฉันชอบหนึ่งสมุทรเนื่องจากพวกเขาง่ายสำหรับฉัน และยังเร็วกว่าเพื่อตรวจสอบมูลค่าทางออกเมื่อเทียบกับการใช้if