จะตรวจสอบได้อย่างไรว่า $ 1 และ $ 2 เป็นโมฆะ?


40

ฉันใช้งานสคริปต์ที่ผ่านการโต้แย้งสตริงและฉันต้องการจะทำอย่างไรถ้าคำสั่งอื่นที่แสดงด้านล่าง

if [ $1 != '' ] && [ $2 != '' ]
then 
    do something.....

Error too many argumentแต่มันก็แสดงให้เห็นว่า ทำไม?


คุณควรจัดเตรียม 1. คำสั่งที่คุณเรียกใช้สคริปต์และ 2. เอาต์พุตเต็ม
Lucio

2
[[ ]]คุณควรใช้ มิฉะนั้นคุณต้องพูดตัวแปรของคุณ
Christophe De Troyer

หากไม่มี $ 1 ดังนั้น $ 2 จะกลายเป็น $ 1 ซึ่งทำให้การทดสอบ $ 1 และ $ 2 ทั้งคู่เป็นโมฆะดูเหมือนไม่เกี่ยวข้อง
WinEunuuchs2Unix

@ WinEunuuchs2Unix ไม่จำเป็นต้องไม่เกี่ยวข้อง - ในบางกรณีคุณต้องการให้แน่ใจว่ามีบางสิ่งบางอย่างแทนสตริงว่างหรือ null ในอาร์กิวเมนต์ $1สามารถยกเลิกการตั้งค่าหรือตั้งค่าเป็นสตริงที่ว่างโดยผู้ใช้ของสคริปต์ พิจารณาลำดับของคำสั่งนี้$ set '' barจากนั้นecho "x${1}x";ตั้งค่าตัวแปรทั้งสอง แต่หนึ่งในนั้นเป็นโมฆะ
Sergiy Kolodyazhnyy

คำตอบ:


55

ลองใช้การทดสอบ -z:

if [ -z "$1" ] && [ -z "$2" ]

จากมนุษย์bash:

-z string
   True if the length of string is zero.

มันใช้งานได้สำหรับฉัน!
pengisgood

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

เมื่อเขียนเชลล์สคริปต์แบบพกพาควรใช้แฟล็กนี้ด้วยความระมัดระวังเนื่องจากในยูนิกซ์เชิงพาณิชย์บางอย่างแฟล็กนี้มีข้อผิดพลาด ดูคำตอบของฉันสำหรับแหล่งข้อมูลที่เชื่อมโยง
Sergiy Kolodyazhnyy


3

ต่อไปนี้ยังใช้งานได้

if [ "$1" == "" && "$2" == ""]; then
    echo NULL
fi

&&และอื่น ๆ testที่แยกคำสั่งตรรกะไม่ได้รับอนุญาตในคลาสสิก คุณต้องใช้โครงสร้างการทดสอบอื่นแทน (เช่น-aฉันคิดว่า)
muru

3

สำหรับคำตอบเวอร์ชันเก่าให้ดูส่วนที่สองของคำตอบนี้ หากคุณต้องการทราบรายละเอียดให้อ่านต่อ

สาเหตุของปัญหา

ในคำถามตัวเองมีรายงานว่า OP เห็นtoo many arguments errorซึ่งเมื่อทดสอบในbashดูเหมือนจะไม่เป็นกรณี:

$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected

ด้วย/bin/shซึ่งเป็น symlinked จริง/bin/dashบน Ubuntu, รายงานข้อผิดพลาดดังต่อไปนี้:

$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator

และสแตนด์อโลน/bin/testยัง:

$ /usr/bin/test $1 != ''  
/usr/bin/test: missing argument after ‘’

Sidenote: หากคุณสงสัยว่าอะไรคืออะไร/usr/bin/testและทำไมฉันถึงใช้งานbashและshคุณควรรู้ว่านั่น[คือนามแฝงสำหรับtestคำสั่งซึ่งยังมีอยู่ว่าเป็นปฏิบัติการแบบสแตนด์อโลนหรือมากกว่าปกติ - เป็นเชลล์ในตัวซึ่งเป็นสิ่งที่แต่ละเชลล์จะใช้ก่อน . สำหรับifคำสั่งพวกเขาทำงานกับรูปปั้นทางออกของคำสั่งดังนั้นทำไม[และtestเป็นคำสั่งด้วยทุกสิ่งที่เป็นข้อโต้แย้งกับคำสั่งนั้น - ลำดับที่ไม่เหมาะสมของ args บรรทัดคำสั่งเหล่านั้นนำไปสู่ข้อผิดพลาด

กลับไปที่หัวข้อ: มันไม่ชัดเจนว่า OP ได้รับข้อผิดพลาดที่ไม่เกี่ยวข้องอย่างไร อย่างไรก็ตามในทั้ง 3 กรณีปัญหาจะเหมือนกัน - ตัวแปรที่ไม่ได้ตั้งค่าจะถือว่าว่างเปล่าดังนั้นสิ่งที่เชลล์เห็นพร้อมกับตัวแปรที่ไม่ได้อ้างอิง

[ != '' ]

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

$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ] 
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars

วิธีที่ดีกว่าในการทดสอบตัวแปรที่ไม่มีการตั้งค่า

วิธีการที่พบเห็นบ่อยมากคือ:

 if [ "x$var1" == "x"  ] && [ "x$var2" == "x"  ];                                                                
 then
     echo "both variables are null"
 fi

หากต้องการอ้างอิงGilles :

ใน ["x $ 1" = "x"] คำนำหน้า x ช่วยให้มั่นใจได้ว่า x "$ 1" อาจดูไม่เหมือนโอเปอเรเตอร์ดังนั้นวิธีเดียวที่เชลล์สามารถแยกวิเคราะห์การทดสอบนี้ได้คือการปฏิบัติ = เป็นโอเปอเรเตอร์ไบนารี

สันนิษฐานว่าน่าจะพกพาได้พอสมควรเพราะฉันเห็นสิ่งเหล่านี้ใน/bin/shสคริปต์ นอกจากนี้ยังสามารถรวมกันเป็นระบบ

if [ "x${var1}${var2}" == "x" ]; then
    ...
fi

แน่นอนว่าเราสามารถใช้-zธงได้อย่างไรก็ตามจากการวิจัยในหอยบางตัวโดยเฉพาะ ksh88 (ตามStephane Chazelas ) ธงนี้ผิดพลาด

ดูสิ่งนี้ด้วย


+1 สำหรับแนวทางที่น่าสนใจมาก
WinEunuuchs2Unix

@ WinEunuuchs2Unix แก้ไขเพื่อให้น่าสนใจยิ่งขึ้น :)
Sergiy Kolodyazhnyy

1

ฉันคิดว่าชื่อของโพสต์ไม่ถูกต้องเนื่องจากความตั้งใจในข้อความนั้นคือการตรวจสอบว่า $ 1 และ $ 2 ไม่เป็นโมฆะ ตัวอย่างที่ได้รับหายไปเพียงสองคำพูดใน $ 1 และ $ 2 ในการทำงาน ตัวแปรต้องอยู่ในเครื่องหมายคำพูดคู่เพื่อขยายเมื่อเปรียบเทียบสตริง แต่เพื่อตรวจสอบว่ามี $ 1 และ $ 2 เหมือนกันกับตรวจสอบว่ามี $ 2 อยู่หรือไม่เพราะมันไม่มีอยู่ถ้า $ 1 ไม่มี คำสั่ง 'if' ไม่จำเป็นในกรณีนี้เช่นกันเมื่อ 'test' ส่งคืนจริง / เท็จและใช้ '&&' เป็น 'จากนั้น' ถ้าส่งคืนเป็น 0 / true:

[ "$2" != '' ] && commands...

เรียบง่ายด้วย -n (ไม่ใช่ศูนย์):

[ -n "$2" ] && commands...

หากต้องการ "ตรวจสอบว่า $ 1 และ $ 2 เป็นโมฆะ" จะเหมือนกับการตรวจสอบหากไม่มีพารามิเตอร์:

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