การเขียนสคริปต์ bash: หากอาร์กิวเมนต์มีค่าเท่ากับสตริงนี้ให้กำหนดตัวแปรเช่นเดียวกับสตริงนี้


225

ฉันกำลังทำสคริปต์ทุบตีและตอนนี้ฉันได้รับการเรียกตัวแปรsourceหนึ่งและหนึ่งอาร์เรย์เรียกว่าsamplesเช่นนี้:

source='country'
samples=(US Canada Mexico...)

เนื่องจากฉันต้องการขยายจำนวนแหล่งข้อมูล (และแหล่งที่มาแต่ละแห่งมีตัวอย่างของตัวเอง) ฉันพยายามเพิ่มอาร์กิวเมนต์บางอย่างเพื่อทำสิ่งนี้ ฉันลองสิ่งนี้:

source=""
samples=("")
if [ $1="country" ]; then
   source="country"
   samples="US Canada Mexico..."
else
   echo "try again"
fi

แต่เมื่อฉันเรียกใช้สคริปต์ของฉันsource countries.sh countryมันไม่ทำงาน ผมทำอะไรผิดหรือเปล่า?


2
มันไม่ทำงานอย่างไร เมื่อคุณเรียกใช้คุณได้รับข้อผิดพลาดหรือมีข้อความว่า "ลองอีกครั้ง" หรืออย่างอื่น
ออตโตชั่วร้าย

2
ใช่คุณอาจคิดว่า 'คำถามตรงไปตรงมามาก' แต่คุณได้คิดถึงเรื่องนี้มาระยะหนึ่งแล้ว โปรดพิจารณาแก้ไขคำถามของคุณเพื่อรวมเอาท์พุทที่จำเป็นและข้อความผิดพลาดที่คุณได้รับ +1 สำหรับลองใช้งานจริงและจัดรูปแบบคำถามให้ดี โชคดี.
shellter

ทำไมรหัสนี้เหมือนกับโซลูชั่นที่เสนอและยอมรับ? สับสน ... ฉันเดาว่าคำถามแรกไม่มีช่องว่างหลังวงเล็บเปิดและหน้าวงเล็บปิดหากประโยค?
Stef

6
@Stef ถ้าคุณมองอย่างใกล้ชิด$1="country"กับ$1 = "country"
จะ

คำตอบ:


413

อย่าลืมช่องว่าง:

source=""
samples=("")
if [ $1 = "country" ]; then
   source="country"
   samples="US Canada Mexico..."
else
  echo "try again"
fi

121
ฉันไม่อยากจะเชื่อเลยว่าฉันใช้เวลาสามชั่วโมงในการทำสิ่งนี้และเป็นปัญหาของช่องว่าง !!!! ... ขอบคุณ @Alex
Alejandro

1
ทำไมคุณใช้samples="US Canada Mexico..."หลังจากการแนะนำการสร้างอาร์เรย์ก่อนsamples=(US Canada Mexico...)?
ผู้ใช้ที่ไม่รู้จัก

10
ฉันพบปัญหาเกี่ยวกับสิ่งนี้เมื่อตัวแปรทางด้านซ้ายเป็นสตริงว่าง if [ "$1" = "country" ]; thenแก้ไขเป็น
andrewb

8
ตกลงนั่นแหล่ะ Bash ได้รับการโหวตอย่างเป็นทางการจาก Beeing ภาษาคำสั่งที่ล้าสมัยที่สุด แต่ยังคงใช้ภาษาคำสั่งอยู่ วากยสัมพันธ์เป็นเรื่องที่ไม่เข้าใจง่ายเลยมันเจ็บปวด ไม่มีที่สำหรับมันในปี 2559+ @Systemd ผู้เขียน: คุณช่วยสร้าง "การสร้างเปลือก Linux ที่ไม่ดูด" โครงการต่อไปของคุณได้หรือไม่? ฉันจะโยนเงินใส่คุณ
masi

3
@masi บางครั้งฉันคิดว่าเจตนาดั้งเดิมของยูนิกซ์คือ "ความปลอดภัยของงานผ่านความสับสน" หากเครื่องมือมีความลับในการใช้ยากที่จะเข้าใจและโดยทั่วไปแล้วหากไม่ได้ใช้ความรู้ที่ไม่ได้รับการฝึกฝนจากผู้เชี่ยวชาญไปจนถึง padwan ก็จะทำให้แน่ใจได้ว่าจะมีการทำงานสำหรับผู้ที่ "รู้" อยู่เสมอ ปรัชญานี้เห็นได้ชัดในโครงสร้าง "RFC" ทั้งหมดและภาษาดอกไม้ที่ใช้ในเอกสารของมนุษย์ซึ่งในขณะที่ในทางเทคนิคบอกให้คุณทราบถึงวิธีการใช้เครื่องมือจริง ๆ แล้วแค่อยู่ที่นั่นเพื่อตอบสนองความต้องการของการจัดทำเอกสารเครื่องมือ มีการเปลี่ยนแปลงเล็กน้อย
ไนซ์

184

คุณสามารถใช้โอเปอเรเตอร์ "=" หรือ "==" สำหรับการเปรียบเทียบสตริงใน bash ปัจจัยที่สำคัญคือการเว้นวรรคภายในวงเล็บ วิธีการที่เหมาะสมสำหรับวงเล็บที่มีระยะห่างภายในและตัวดำเนินการเพื่อให้มีการเว้นวรรค ในบางกรณีชุดค่าผสมต่างกันจะทำงาน อย่างไรก็ตามสิ่งต่อไปนี้มีวัตถุประสงค์เพื่อเป็นตัวอย่างสากล

if [ "$1" == "something" ]; then     ## GOOD

if [ "$1" = "something" ]; then      ## GOOD

if [ "$1"="something" ]; then        ## BAD (operator spacing)

if ["$1" == "something"]; then       ## BAD (bracket spacing)

นอกจากนี้โน้ตคู่นั้นได้รับการจัดการแตกต่างกันเล็กน้อยเมื่อเทียบกับวงเล็บเดียว ...

if [[ $a == z* ]]; then   # True if $a starts with a "z" (pattern matching).
if [[ $a == "z*" ]]; then # True if $a is equal to z* (literal matching).

if [ $a == z* ]; then     # File globbing and word splitting take place.
if [ "$a" == "z*" ]; then # True if $a is equal to z* (literal matching).

ฉันหวังว่าจะช่วย!


12

ดูเหมือนว่าคุณต้องการแยกอาร์กิวเมนต์บรรทัดคำสั่งลงในสคริปต์ทุบตีของคุณ ฉันได้ค้นหาสิ่งนี้ด้วยตัวเองเมื่อเร็ว ๆ นี้ ฉันเจอสิ่งต่อไปนี้ซึ่งฉันคิดว่าจะช่วยคุณในการแยกวิเคราะห์ข้อโต้แย้ง:

http://rsalveti.wordpress.com/2007/04/03/bash-parsing-arguments-with-getopts/

ฉันเพิ่มตัวอย่างข้อมูลด้านล่างเป็น tl; dr

#using : after a switch variable means it requires some input (ie, t: requires something after t to validate while h requires nothing.
while getopts ht:r:p:v OPTION
do
     case $OPTION in
         h)
             usage
             exit 1
             ;;
         t)
             TEST=$OPTARG
             ;;
         r)
             SERVER=$OPTARG
             ;;
         p)
             PASSWD=$OPTARG
             ;;
         v)
             VERBOSE=1
             ;;
         ?)
             usage
             exit
             ;;
     esac
done

if [[ -z $TEST ]] || [[ -z $SERVER ]] || [[ -z $PASSWD ]]
then
     usage
     exit 1
fi

./script.sh -t ทดสอบ -r เซิร์ฟเวอร์ -p รหัสผ่าน -v

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.