ฉันสับสนโดยการใช้วงเล็บวงเล็บวงเล็บปีกกาใน Bash เช่นเดียวกับความแตกต่างระหว่างรูปแบบสองหรือเดี่ยวของพวกเขา มีคำอธิบายที่ชัดเจนหรือไม่?
ฉันสับสนโดยการใช้วงเล็บวงเล็บวงเล็บปีกกาใน Bash เช่นเดียวกับความแตกต่างระหว่างรูปแบบสองหรือเดี่ยวของพวกเขา มีคำอธิบายที่ชัดเจนหรือไม่?
คำตอบ:
ใน Bash test
และ[
เป็น shell builtins
เครื่องหมายวงเล็บเหลี่ยมคู่ซึ่งเป็นคีย์เวิร์ดเชลล์เปิดใช้งานฟังก์ชันเพิ่มเติม ตัวอย่างเช่นคุณสามารถใช้&&
และ||
แทนที่-a
และ-o
และมีตัวดำเนินการจับคู่นิพจน์ทั่วไป=~
และมีผู้ประกอบการแสดงออกของการจับคู่ปกติ
นอกจากนี้ในการทดสอบอย่างง่ายวงเล็บเหลี่ยมสองชั้นดูเหมือนจะประเมินได้เร็วกว่าแบบเดี่ยวมาก
$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done
real 0m24.548s
user 0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done
real 0m33.478s
user 0m33.478s
sys 0m0.000s
เครื่องมือจัดฟันนอกเหนือจากการกำหนดชื่อตัวแปรให้ใช้สำหรับการขยายพารามิเตอร์เพื่อให้คุณสามารถทำสิ่งต่าง ๆ เช่น:
ตัดเนื้อหาของตัวแปรออก
$ var="abcde"; echo ${var%d*}
abc
ทำให้การทดแทนคล้ายกับ sed
$ var="abcde"; echo ${var/de/12}
abc12
ใช้ค่าเริ่มต้น
$ default="hello"; unset var; echo ${var:-$default}
hello
และอีกมากมาย
นอกจากนี้การขยายรั้งจะสร้างรายการของสตริงซึ่งโดยทั่วไปจะวนซ้ำในลูป:
$ echo f{oo,ee,a}d
food feed fad
$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")
$ for num in {000..2}; do echo "$num"; done
000
001
002
$ echo {00..8..2}
00 02 04 06 08
$ echo {D..T..4}
D H L P T
โปรดทราบว่าคุณลักษณะนำหน้าศูนย์และการเพิ่มขึ้นไม่พร้อมใช้งานก่อน Bash 4
ขอบคุณ gboffi สำหรับเตือนฉันเกี่ยวกับการขยายรั้ง
เครื่องหมายวงเล็บคู่ใช้สำหรับการดำเนินการทางคณิตศาสตร์ :
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
และพวกเขาทำให้คุณสามารถละเว้นเครื่องหมายดอลลาร์เกี่ยวกับตัวแปรจำนวนเต็มและอาร์เรย์และรวมถึงการเว้นวรรครอบตัวดำเนินการเพื่อให้สามารถอ่านได้
วงเล็บเดียวยังใช้สำหรับดัชนีอาร์เรย์ :
array[4]="hello"
element=${array[index]}
ต้องใช้เครื่องหมายปีกกาสำหรับการอ้างอิงอาเรย์ (ส่วนใหญ่ / ทั้งหมด?) ทางด้านขวามือ
ความคิดเห็นของ ephemientทำให้ฉันนึกถึงว่ามีการใช้วงเล็บใน subshells ด้วยเช่นกัน และพวกเขาจะใช้ในการสร้างอาร์เรย์
array=(1 2 3)
echo ${array[1]}
2
:
มันเป็นเพียงระเบิดส้อมถ้าคุณเรียกมันเพิ่มเติมด้วย
$[expression]
; นี่คือไวยากรณ์นิพจน์ทางคณิตศาสตร์เก่าที่คัดค้านสำหรับไวยากรณ์ที่ใหม่กว่าและต้องการ:$((expression))
bash
การสร้างลำดับดังที่กล่าวไว้ด้านล่าง ( stackoverflow.com/a/8552128/2749397 ) ตามที่ฉันต้องการจะแสดงความคิดเห็นเล็กน้อยคุณลักษณะนี้ (ตามที่คุณไม่ได้พูดถึงมัน ;-) ฉัน ' m ใช้เสรีภาพในการใช้คำตอบที่ได้รับการโหวตมากที่สุดในฐานะพาหนะ ... ตัวอย่างสองตัวอย่างของตัวอักษรตามลำดับ: echo {01..12}
-> 01 02 03 04 05 06 07 08 09 10 11 12
(บันทึกศูนย์เริ่มต้น); ->echo {C..Q}
C D E F G H I J K L M N O P Q
การใช้งานหลักคือลูปเช่น for cnt in {01..12} ; do ... ${cnt} ... ; done
echo {01..12..2}
-> "01 03 05 07 09 11" ขอบคุณสำหรับการเตือนเกี่ยวกับลำดับ ฉันจะเพิ่มเข้าไปในคำตอบของฉัน
เครื่องหมายวงเล็บเดี่ยว ( [
) มักจะเรียกชื่อโปรแกรม[
จริง man test
หรือman [
สำหรับข้อมูลเพิ่มเติม ตัวอย่าง:
$ VARIABLE=abcdef
$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
yes
วงเล็บคู่ ( [[
) ทำสิ่งเดียวกัน (โดยทั่วไป) เป็นวงเล็บเดียว แต่เป็นตัวทุบตีในตัว
$ VARIABLE=abcdef
$ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
no
วงเล็บ ( ()
) ถูกใช้เพื่อสร้าง subshell ตัวอย่างเช่น:
$ pwd
/home/user
$ (cd /tmp; pwd)
/tmp
$ pwd
/home/user
อย่างที่คุณเห็น subshell อนุญาตให้คุณทำการดำเนินการโดยไม่มีผลกระทบต่อสภาพแวดล้อมของเชลล์ปัจจุบัน
(a) เครื่องมือจัดฟัน ( {}
) ใช้เพื่อระบุตัวแปรอย่างไม่น่าสงสัย ตัวอย่าง:
$ VARIABLE=abcdef
$ echo Variable: $VARIABLE
Variable: abcdef
$ echo Variable: $VARIABLE123456
Variable:
$ echo Variable: ${VARIABLE}123456
Variable: abcdef123456
(b) การจัดฟันใช้เพื่อดำเนินการตามลำดับของคำสั่งในบริบทเชลล์ปัจจุบันเช่น
$ { date; top -b -n1 | head ; } >logfile
# 'date' and 'top' output are concatenated,
# could be useful sometimes to hunt for a top loader )
$ { date; make 2>&1; date; } | tee logfile
# now we can calculate the duration of a build from the logfile
มีความแตกต่างทางวากยสัมพันธ์ที่ลึกซึ้งด้วย( )
แม้ว่า (ดูการอ้างอิงทุบตี ); หลักอัฒภาค;
หลังจากที่คำสั่งสุดท้ายที่อยู่ในวงเล็บคือต้องและวงเล็บ{
, }
ต้องถูกล้อมรอบด้วยช่องว่าง
[
เป็นจริงใน builtin ทุบตี แต่มันควรจะทำหน้าที่เหมือน/bin/[
เมื่อเทียบกับ[[
ในตัว [[
มีคุณสมบัติที่แตกต่างกันเช่นการทำงานแบบลอจิคัลมากกว่าและบทบาทที่ต่างกัน นอกจากนี้: วงเล็บเดียวยังใช้สำหรับอาร์เรย์การแทนกระบวนการและการขยายเพิ่มเติม เครื่องหมายวงเล็บคู่ใช้สำหรับการคำนวณ วงเล็บปีกกา{}
จะใช้สำหรับการจัดกลุ่มคำสั่งหรือหลากหลายประเภทของการขยายพารามิเตอร์หรือการขยายรั้งหรือการขยายลำดับ ฉันแน่ใจว่าฉันพลาดการใช้งานอื่นด้วย
if [ $VARIABLE == abcdef ]
คือ bashism ที่แม้ว่ามันจะใช้ได้ดี แต่ก็ควรหลีกเลี่ยง ใช้ bash ( if [[ ...==...]]
) อย่างชัดเจนหรือทำให้ชัดเจนว่าคุณใช้เงื่อนไขแบบดั้งเดิมมากขึ้น ( if [ "$VARIABLE" = "abcdef" ]
) เนื้อหาควรเริ่มจากสคริปต์ที่เรียบง่ายและพกพาได้มากที่สุดจนกว่าพวกเขาจะต้องการคุณลักษณะเฉพาะสำหรับการทุบตี (ด้วยเหตุผลใดก็ตาม) แต่ไม่ว่าในกรณีใดเจตนาจะชัดเจน "=" และ "==" และ "[[" และ "[" ทำงานแตกต่างกันและการใช้งานควรสอดคล้องกัน
[ "$var" = ".."]
แทนที่จะเป็น==
ในขณะที่ C จะกำหนดแทนการทดสอบ (และค่อนข้างเป็นสาเหตุของข้อบกพร่อง) ... ทำไมไม่ 'T test
ใช้==
แทน=
? มีใครรู้บ้าง
/usr/bin/[
ไม่ใช่ symlink ไป/usr/bin/test
และอื่น ๆ : โปรแกรมเหล่านี้มีขนาดแตกต่างกันเล็กน้อย!
)
เป็นส่วนหนึ่งของcase
ไวยากรณ์คำสั่งเพื่อสิ้นสุดบรรทัดเคส มันไม่มีวงเล็บเปิด นี่เป็นการขว้างฉันครั้งแรกที่ฉันเห็นมัน
วงเล็บ
if [ CONDITION ] Test construct
if [[ CONDITION ]] Extended test construct
Array[1]=element1 Array initialization
[a-z] Range of characters within a Regular Expression
$[ expression ] A non-standard & obsolete version of $(( expression )) [1]
[1] http://wiki.bash-hackers.org/scripting/obsolete
วงเล็บปีกกา
${variable} Parameter substitution
${!variable} Indirect variable reference
{ command1; command2; . . . commandN; } Block of code
{string1,string2,string3,...} Brace expansion
{a..z} Extended brace expansion
{} Text replacement, after find and xargs
วงเล็บ
( command1; command2 ) Command group executed within a subshell
Array=(element1 element2 element3) Array initialization
result=$(COMMAND) Command substitution, new style
>(COMMAND) Process substitution
<(COMMAND) Process substitution
วงเล็บคู่
(( var = 78 )) Integer arithmetic
var=$(( 20 + 5 )) Integer arithmetic, with variable assignment
(( var++ )) C-style variable increment
(( var-- )) C-style variable decrement
(( var0 = var1<98?9:21 )) C-style ternary operation
ฉันแค่อยากจะเพิ่มสิ่งเหล่านี้จากTLDP :
~:$ echo $SHELL
/bin/bash
~:$ echo ${#SHELL}
9
~:$ ARRAY=(one two three)
~:$ echo ${#ARRAY}
3
~:$ echo ${TEST:-test}
test
~:$ echo $TEST
~:$ export TEST=a_string
~:$ echo ${TEST:-test}
a_string
~:$ echo ${TEST2:-$TEST}
a_string
~:$ echo $TEST2
~:$ echo ${TEST2:=$TEST}
a_string
~:$ echo $TEST2
a_string
~:$ export STRING="thisisaverylongname"
~:$ echo ${STRING:4}
isaverylongname
~:$ echo ${STRING:6:5}
avery
~:$ echo ${ARRAY[*]}
one two one three one four
~:$ echo ${ARRAY[*]#one}
two three four
~:$ echo ${ARRAY[*]#t}
one wo one hree one four
~:$ echo ${ARRAY[*]#t*}
one wo one hree one four
~:$ echo ${ARRAY[*]##t*}
one one one four
~:$ echo $STRING
thisisaverylongname
~:$ echo ${STRING%name}
thisisaverylong
~:$ echo ${STRING/name/string}
thisisaverylongstring
echo ${#ARRAY}
แสดงสามเพราะองค์ประกอบแรกของARRAY
ประกอบด้วยสามอักขระไม่ใช่เพราะมันมีสามองค์ประกอบ! echo ${#ARRAY[@]}
หากต้องการพิมพ์จำนวนการใช้องค์ประกอบ
${TEST:-test}
เท่ากับ$TEST
ว่ามีตัวแปรTEST
อยู่มิฉะนั้นจะส่งคืนสตริง "test" มีอีกเวอร์ชั่นหนึ่งที่ทำอะไรได้มากกว่า: ${TEST:=test}
--- ซึ่งเท่ากับ$TEST
ถ้ามีการทดสอบอยู่ แต่เมื่อใดก็ตามที่ไม่มีก็จะสร้างตัวแปรTEST
และกำหนดค่า "ทดสอบ" และยังกลายเป็นค่าของนิพจน์ทั้งหมด
ความแตกต่างระหว่างการทดสอบ , [และ[[มีการอธิบายในรายละเอียดมากในBashFAQ
หากต้องการตัดเรื่องสั้นให้สั้น: ทดสอบใช้ไวยากรณ์แบบพกพาเก่าของคำสั่ง ในเชลล์เกือบทั้งหมด (เชลล์ Bourne ที่เก่าที่สุดเป็นข้อยกเว้น), [เป็นคำพ้องสำหรับการทดสอบ (แต่ต้องการอาร์กิวเมนต์สุดท้ายของ) แม้ว่าเชลล์ที่ทันสมัยทั้งหมดมีการใช้งานในตัวของ [แต่ก็ยังคงมีความสามารถในการเรียกใช้งานภายนอกของชื่อนั้นได้เช่น / bin / [
[[เป็นรุ่นที่ปรับปรุงใหม่ของมันซึ่งเป็นคำหลักไม่ใช่โปรแกรม สิ่งนี้มีผลประโยชน์ในการใช้งานง่ายดังแสดงด้านล่าง [[เข้าใจโดย KornShell และ BASH (เช่น 2.03) แต่ไม่ใช่ POSIX หรือ BourneShell ที่เก่ากว่า
และข้อสรุป:
คำสั่งทดสอบใหม่ [ควรจะใช้เมื่อไรและเมื่อไหร่? หากการพกพาไปยัง BourneShell เป็นเรื่องที่น่ากังวลควรใช้ไวยากรณ์เก่า หากในอีกทางหนึ่งสคริปต์ต้องการ BASH หรือ KornShell ไวยากรณ์ใหม่นั้นมีความยืดหยุ่นมากกว่า
()
กำลังใช้
วงเล็บในคำจำกัดความของฟังก์ชัน:
function_name () { command1 ; command2 ; }
นั่นคือเหตุผลที่คุณต้องหลีกเลี่ยงวงเล็บในพารามิเตอร์คำสั่ง:
$ echo (
bash: syntax error near unexpected token `newline'
$ echo \(
(
$ echo () { command echo The command echo was redefined. ; }
$ echo anything
The command echo was redefined.
unset -f echo
@ChanKim: help unset
ดู
Truncate the contents of a variable
$ var="abcde"; echo ${var%d*}
abc
Make substitutions similar to sed
$ var="abcde"; echo ${var/de/12}
abc12
Use a default value
$ default="hello"; unset var; echo ${var:-$default}
hello