Câu trả lời:
Không có giấy tờ , nhưng hoạt động trong mọi phiên bản tôi đã chạy đểsh
tương thích ngược:
for
vòng lặp cho phép bạn sử dụng {
}
thay vì do
done
. Ví dụ: thay thế:
for i in {1..10};do echo $i; done
với:
for i in {1..10};{ echo $i;}
sh
và Bash cũng cho phép nó vì điều đó, mặc dù buồn là tôi không có một trích dẫn.
csh
có lẽ - đó là cách họ làm việc trong cái vỏ đó.
ksh93
những điều trên có thể là: ;{1..10}
và trong bash
:printf %s\\n {1..10}
for((;i++<10)){ echo $i;}
ngắn hơnfor i in {1..10};{ echo $i;}
Để sử dụng mở rộng số học $[…]
thay vì $((…))
:
bash-4.1$ echo $((1+2*3))
7
bash-4.1$ echo $[1+2*3]
7
Trong các mở rộng số học không sử dụng $
:
bash-4.1$ a=1 b=2 c=3
bash-4.1$ echo $[$a+$b*$c]
7
bash-4.1$ echo $[a+b*c]
7
Mở rộng số học được thực hiện trên các chỉ mục mảng được lập chỉ mục, vì vậy không sử dụng $
cả ở đó:
bash-4.1$ a=(1 2 3) b=2 c=3
bash-4.1$ echo ${a[$c-$b]}
2
bash-4.1$ echo ${a[c-b]}
2
Trong các mở rộng số học không sử dụng ${…}
:
bash-4.1$ a=(1 2 3)
bash-4.1$ echo $[${a[0]}+${a[1]}*${a[2]}]
7
bash-4.1$ echo $[a[0]+a[1]*a[2]]
7
while((i--))
, hoạt động, với while[i--]
hoặc while $[i--]
không làm việc cho tôi. GNU bash, phiên bản 4.3.46 (1)
y=`bc<<<"($x*2.2)%10/1"`
... ví dụ về việc sử dụng bc
cho các phép tính không nguyên ... lưu ý /1
ở cuối rút ngắn số thập phân kết quả thành một số nguyên.
s=$((i%2>0?s+x:s+y))
... ví dụ về việc sử dụng toán tử ternary trong số học bash. Nó ngắn hơn if..then..else
hoặc[ ] && ||
GNU bash, version 5.0.2(1)-release (x86_64-apple-darwin16.7.0)
và nó không phải của tôi.
Cách bình thường, dài và nhàm chán để xác định hàm là
f(){ CODE;}
Như anh chàng này phát hiện ra, bạn hoàn toàn cần không gian trước CODE
và dấu chấm phẩy sau nó.
Đây là một mẹo nhỏ mà tôi đã học được từ @DigitalTrauma :
f()(CODE)
Đó là hai ký tự ngắn hơn và nó cũng hoạt động tốt, với điều kiện là bạn không cần phải thực hiện bất kỳ thay đổi nào trong các giá trị của biến sau khi hàm trả về ( dấu ngoặc đơn chạy phần thân trong một khung con ).
Như @ jimmy23013 chỉ ra trong các bình luận, ngay cả dấu ngoặc đơn cũng có thể không cần thiết.
Các tay Bash Reference cho thấy chức năng này có thể được định nghĩa như sau:
name () compound-command [ redirections ]
hoặc là
function name [()] compound-command [ redirections ]
Một lệnh ghép có thể là:
until
, while
hoặcfor
if
, case
, ((...))
hoặc[[...]]
(...)
hoặc{...}
Điều đó có nghĩa là tất cả những điều sau đây là hợp lệ:
$ f()if $1;then $2;fi
$ f()($1&&$2)
$ f()(($1)) # This one lets you assign integer values
Và tôi đã sử dụng dấu ngoặc nhọn như một cái mút ...
f()while ...
f()if ...
và các lệnh ghép khác.
f()CODE
là hợp pháp. Hóa ra đó f()echo hi
là hợp pháp trong pdksh và zsh, nhưng không phải trong bash.
for
việc nó mặc định theo vị trí: f()for x do : $x; done;set -x *;PS4=$* f "$@"
hoặc một cái gì đó.
:
là một lệnh không làm gì cả, trạng thái thoát của nó luôn thành công, vì vậy nó có thể được sử dụng thay thế true
.
:(){:|:}
Thêm lời khuyên
Lạm dụng toán tử ternary, ((test)) && cmd1 || cmd2
hoặc [ test ] && cmd1 || cmd2
, càng nhiều càng tốt.
Ví dụ (số lượng chiều dài luôn loại trừ dòng trên cùng):
t="$something"
if [ $t == "hi" ];then
cmd1
cmd2
elif [ $t == "bye" ];then
cmd3
cmd4
else
cmd5
if [ $t == "sup" ];then
cmd6
fi
fi
Bằng cách chỉ sử dụng các toán tử ternary, điều này có thể dễ dàng rút ngắn thành:
t="$something"
[ $t == "hi" ]&&{
cmd1;cmd2
}||[ $t == "bye" ]&&{
cmd3;cmd4
}||{
cmd5
[ $t == "sup" ]&&cmd6
}
Như nyuszika7h đã chỉ ra trong các bình luận, ví dụ cụ thể này có thể được rút ngắn hơn nữa bằng cách sử dụng case
:
t="$something"
case $t in "hi")cmd1;cmd2;;"bye")cmd3;cmd4;;*)cmd5;[ $t == "sup" ]&&cmd6;esac
Ngoài ra, thích dấu ngoặc đơn để niềng răng càng nhiều càng tốt. Vì dấu ngoặc đơn là một metacharacter, và không phải là một từ, chúng không bao giờ yêu cầu khoảng trắng trong bất kỳ bối cảnh nào. Điều này cũng có nghĩa là chạy càng nhiều lệnh trong một lớp con càng tốt, bởi vì dấu ngoặc nhọn (nghĩa là {
và }
) là các từ dành riêng, không phải là ký tự meta và do đó phải có khoảng trắng ở cả hai bên để phân tích chính xác, nhưng các ký tự meta thì không. Tôi giả sử rằng bây giờ bạn biết rằng các lớp con không ảnh hưởng đến môi trường cha, vì vậy giả sử rằng tất cả các lệnh ví dụ có thể được chạy một cách an toàn trong một lớp con (không phải là điển hình trong mọi trường hợp), bạn có thể rút ngắn đoạn mã trên thành điều này :
t=$something
[ $t == "hi" ]&&(cmd1;cmd2)||[ $t == "bye" ]&&(cmd3;cmd4)||(cmd5;[ $t == "sup" ]&&cmd6)
Ngoài ra, nếu bạn không thể, sử dụng dấu ngoặc đơn vẫn có thể giảm bớt một số. Một điều cần lưu ý là nó chỉ hoạt động cho các số nguyên, điều này làm cho nó vô dụng cho các mục đích của ví dụ này (nhưng nó tốt hơn nhiều so với sử dụng -eq
cho các số nguyên).
Một điều nữa, tránh trích dẫn khi có thể. Sử dụng lời khuyên trên, bạn có thể giảm thiểu nó. Thí dụ:
t=$something
[ $t == hi ]&&(cmd1;cmd2)||[ $t == bye ]&&(cmd3;cmd4)||(cmd5;[ $t == sup ]&&cmd6)
Trong điều kiện thử nghiệm, ưu tiên dấu ngoặc đơn cho dấu ngoặc kép càng nhiều càng tốt với một vài ngoại lệ. Nó giảm hai ký tự miễn phí, nhưng trong một số trường hợp, nó không mạnh bằng (đó là phần mở rộng Bash - xem ví dụ bên dưới). Ngoài ra, sử dụng đối số bằng đơn chứ không phải gấp đôi. Đó là một nhân vật miễn phí để thả.
[[ $f == b ]]&&: # ... <-- Bad
[ $f == b ]&&: # ... <-- Better
[ $f = b ]&&: # ... <-- Best. word splits and pathname-expands the contents of $f. Esp. bad if it starts with -
Lưu ý cảnh báo này, đặc biệt là trong việc kiểm tra đầu ra null hoặc một biến không xác định:
[[ $f ]]&&: # double quotes aren't needed inside [[, which can save chars
[ "$f" = '' ]&&: <-- This is significantly longer
[ -n "$f" ]&&:
Trong tất cả các kỹ thuật, ví dụ cụ thể này sẽ là tốt nhất với case
... in
:
t=$something
case $t in hi)cmd1;cmd2;;bye)cmd3;cmd4;;*)cmd5;[ $t == sup ]&&cmd6;esac
Vì vậy, đạo đức của bài này là:
if
/ if-else
/ etc. công trình.case
... in
, vì nó có thể tiết kiệm khá nhiều byte, đặc biệt là khớp chuỗi.PS: Đây là danh sách các ký tự meta được nhận dạng trong Bash bất kể ngữ cảnh (và có thể tách các từ):
< > ( ) ; & | <space> <tab>
EDIT: Như manatwork đã chỉ ra, kiểm tra dấu ngoặc kép chỉ hoạt động đối với các số nguyên. Ngoài ra, gián tiếp, tôi thấy rằng bạn cần phải có khoảng trắng xung quanh ==
toán tử. Sửa bài của tôi ở trên.
Tôi cũng quá lười để tính toán lại độ dài của từng đoạn, vì vậy tôi chỉ cần loại bỏ chúng. Nó phải đủ dễ dàng để tìm một máy tính độ dài chuỗi trực tuyến nếu cần thiết.
[ $t=="hi" ]
sẽ luôn luôn đánh giá về 0, vì nó được phân tích thành [ -n "STRING" ]
. (($t=="hi"))
sẽ luôn luôn ước tính về 0 miễn là $ t có giá trị không phải là số, vì các chuỗi được buộc thành số nguyên trong các đánh giá số học. Một số trường hợp thử nghiệm: pastebin.com/WefDzWbL
case
sẽ được ngắn hơn ở đây. Ngoài ra, bạn không cần một không gian trước }
, nhưng bạn làm sau {
.
=
kém mạnh mẽ hơn ==
? =
được ủy quyền bởi POSIX, ==
không.
Thay vì grep -E
, grep -F
, grep -r
, sử dụng egrep
, fgrep
, rgrep
, tiết kiệm hai ký tự. Những cái ngắn hơn được phản đối nhưng hoạt động tốt.
(Bạn đã yêu cầu một lời khuyên cho mỗi câu trả lời!)
Pgrep
cho grep -P
. Mặc dù tôi thấy làm thế nào nó có thể dễ bị nhầm lẫn pgrep
, được sử dụng để tra cứu các quy trình.
Phần tử 0 của một mảng chỉ có thể được truy cập bằng tên biến, tiết kiệm năm byte so với chỉ định rõ ràng một chỉ số là 0:
$ a=(code golf)
$ echo ${a[0]}
code
$ echo $a
code
$
Nếu bạn cần chuyển nội dung của một biến sang STDIN của quy trình tiếp theo trong một đường ống, thì thông thường sẽ lặp lại biến đó thành một đường ống. Nhưng bạn có thể đạt được điều tương tự với <<<
chuỗi bash ở đây :
$ s="code golf"
$ echo "$s"|cut -b4-6
e g
$ cut -b4-6<<<"$s"
e g
$
s=code\ golf
, echo $s|
và <<<$s
(hãy nhớ rằng sau này hai công việc chỉ vì không có dấu cách lặp đi lặp lại, vv).
Tránh $( ...command... )
, có một cách khác để lưu một char và thực hiện điều tương tự:
` ...command... `
$( )
là cần thiết nếu bạn đã thay thế lệnh lồng nhau; nếu không, bạn phải thoát khỏi nội tâm``
$()
khi tôi muốn chạy thay thế trên máy của mình thay vì scp
máy đích, chẳng hạn. Trong hầu hết các trường hợp chúng giống hệt nhau.
$()
có thể làm nếu bạn trích dẫn mọi thứ đúng cách. (trừ khi bạn cần lệnh của bạn để tồn tại một cái gì đó munges $
nhưng không backticks). Có một số khác biệt tinh tế trong việc trích dẫn những thứ bên trong chúng. mywiki.wooledge.org/BashFAQ/082 giải thích một số khác biệt. Trừ khi bạn đang chơi golf, không bao giờ sử dụng backticks.
echo `bc <<<"\`date +%s\`-12"`
... (Thật khó để gửi mẫu có chứa backtick trong bình luận, đó!)
if
để nhóm lệnhSo với mẹo này loại bỏ if
tất cả, điều này chỉ nên hoạt động tốt hơn trong một số trường hợp rất hiếm, chẳng hạn như khi bạn cần các giá trị trả về từ if
.
Nếu bạn có một nhóm lệnh kết thúc bằng một if
, như sau:
a&&{ b;if c;then d;else e;fi;}
a&&(b;if c;then d;else e;fi)
Bạn có thể bọc các lệnh trước if
trong điều kiện thay thế:
a&&if b;c;then d;else e;fi
Hoặc nếu chức năng của bạn kết thúc bằng if
:
f(){ a;if b;then c;else d;fi;}
Bạn có thể loại bỏ niềng răng:
f()if a;b;then c;else d;fi
[test] && $if_true || $else
trong các hàm này và lưu một số byte.
&&
và||
(( ... ))
cho các điều kiệnBạn có thể thay thế:
if [ $i -gt 5 ] ; then
echo Do something with i greater than 5
fi
bởi
if((i>5));then
echo Do something with i greater than 5
fi
(Lưu ý: Không có không gian sau if
)
hoặc thậm chí
((i>5))&&{
echo Do something with i greater than 5
}
... hoặc nếu chỉ có một lệnh
((i>5))&&echo Echo or do something with i greater than 5
((i>5?c=1:0))&&echo Nothing relevant there...
# ...
((c))&&echo Doing something else if i was greater than 5
hoặc giống nhau
((c=i>5?c=0,1:0))&&echo Nothing relevant there...
# ...
((c))&&echo Doing something else if i was greater than 5
... trong đó nếu i> 5, thì c = 1 (không phải 0;)
[ ]
thay vì (())
.
[ ]
bạn cần ký hiệu đô la cho biến. Tôi không thấy cách bạn có thể làm tương tự với cùng chiều dài hoặc nhỏ hơn bằng cách sử dụng [ ]
.
((...))
, không cần dòng mới hoặc khoảng trắng. Ví dụ: for((;10>n++;)){((n%3))&&echo $n;}
Hãy thử trực tuyến!
Một cú pháp ngắn hơn cho các vòng lặp vô hạn (có thể được thoát bằng break
hoặc các exit
câu lệnh) là
for((;;)){ code;}
Cái này ngắn hơn while true;
và while :;
.
Nếu bạn không cần break
(với exit
cách duy nhất để thoát), bạn có thể sử dụng hàm đệ quy thay thế.
f(){ code;f;};f
Nếu bạn cần nghỉ, nhưng bạn không cần thoát và bạn không cần thực hiện bất kỳ sửa đổi biến nào bên ngoài vòng lặp, bạn có thể sử dụng hàm đệ quy với dấu ngoặc đơn quanh thân , chạy phần thân trong một hàm con.
f()(code;f);f
for
Vòng lặp một dòngMột biểu thức số học được nối với mở rộng phạm vi sẽ được đánh giá cho từng mục trong phạm vi. Ví dụ như sau:
: $[expression]{0..9}
sẽ đánh giá expression
10 lần.
Điều này thường ngắn hơn đáng kể so với for
vòng lặp tương đương :
for((;10>n++;expression with n)){ :;}
: $[expression with ++n]{0..9}
Nếu bạn không thấy lỗi lệnh không tìm thấy, bạn có thể loại bỏ inital :
. Đối với các lần lặp lớn hơn 10, bạn cũng có thể sử dụng phạm vi ký tự, ví dụ như {A..z}
sẽ lặp lại 58 lần.
Như một ví dụ thực tế, cả hai sau đây tạo ra 50 số tam giác đầu tiên, mỗi số trên một dòng riêng của chúng:
for((;50>d++;)){ echo $[n+=d];} # 31 bytes
printf %d\\n $[n+=++d]{A..r} # 28 bytes
for((;0<i--;)){ f;}
Như đã lưu ý trong vòng lặp Bash Bash cho vòng lặp mà không có phần tử trong phần foo bar , phần in "$@;"
trong đó for x in "$@;"
là phần thừa.
Từ help for
:
for: for NAME [in WORDS ... ] ; do COMMANDS; done
Execute commands for each member in a list.
The `for' loop executes a sequence of commands for each member in a
list of items. If `in WORDS ...;' is not present, then `in "$@"' is
assumed. For each element in WORDS, NAME is set to that element, and
the COMMANDS are executed.
Exit Status:
Returns the status of the last command executed.
Ví dụ: nếu chúng ta muốn bình phương tất cả các số được đưa ra đối số vị trí cho tập lệnh Bash hoặc hàm, chúng ta có thể làm điều này.
for n;{ echo $[n*n];}
Giả sử bạn đang cố đọc một tập tin và sử dụng nó trong một cái gì đó khác. Những gì bạn có thể làm là:
echo foo `cat bar`
Nếu nội dung bar
là foobar
, điều này sẽ in foo foobar
.
Tuy nhiên, có một cách khác nếu bạn đang sử dụng phương pháp này, giúp tiết kiệm 3 byte:
echo foo `<bar`
<bar
bản thân nó không hoạt động nhưng đặt nó trong backticks không?
<
đặt một tập tin vào một lệnh, nhưng trong trường hợp này, nó đặt nó vào đầu ra tiêu chuẩn do một sự cố. Các backticks đánh giá điều này cùng nhau.
`cat`
không?
[
thay thế [[
và test
khi có thểThí dụ:
[ -n $x ]
=
thay vì ==
để so sánhThí dụ:
[ $x = y ]
Lưu ý rằng bạn phải có khoảng trắng xung quanh dấu bằng nếu không nó sẽ không hoạt động. Áp dụng tương tự ==
dựa trên các bài kiểm tra của tôi.
[
... ]
== /bin/test
, nhưng [[
... ]]
! = /bin/test
Và người ta không bao giờ nên thích [
... ]
hơn [[
... ]]
bên ngoài codegolf
tr -cd
ngắn hơn grep -o
Ví dụ: nếu bạn cần đếm khoảng trắng, grep -o <char>
(chỉ in phần trùng khớp) sẽ cho 10 byte trong khi tr -cd <char>
(xóa phần bù <char>
) cho 9.
# 16 bytes
grep -o \ |wc -l
# 15 bytes
tr -cd \ |wc -c
( nguồn )
Lưu ý rằng cả hai đều cho đầu ra hơi khác nhau. grep -o
trả về kết quả phân tách dòng trong khi tr -cd
cung cấp tất cả chúng trên cùng một dòng, vì vậy tr
có thể không phải lúc nào cũng thuận lợi.
Trong một thử thách gần đây tôi đã cố gắng đọc tệp /sys/class/power_supply/BAT1/capacity
, tuy nhiên điều này có thể rút ngắn lại /*/*/*/*/capac*y
vì không có tệp nào khác tồn tại với định dạng đó.
Ví dụ: nếu bạn có một thư mục foo/
chứa các tệp foo, bar, foobar, barfoo
và bạn muốn tham chiếu tệp foo/barfoo
, bạn có thể sử dụng foo/barf*
để lưu một byte.
Đại *
diện cho "bất cứ điều gì", và tương đương với regex .*
.
Sử dụng một đường ống để :
lệnh thay vì /dev/null
. Việc tích :
hợp sẽ ăn tất cả đầu vào của nó.
echo a|tee /dev/stderr|:
sẽ không in bất cứ điều gì.
echo a|tee /dev/stderr|:
đã in một cái trên máy tính của tôi, nhưng ở nơi khác SIGPIPE có thể giết tee trước. Nó có thể phụ thuộc vào phiên bản của tee
.
tee >(:) < <(seq 1 10)
sẽ hoạt động, nhưng tee /dev/stderr | :
sẽ không. Thậm chí a() { :;};tee /dev/stderr < <(seq 1 10)| a
không in bất cứ thứ gì.
:
nội tại không ăn gì cả ... nếu bạn cho rằng đầu vào vào dấu hai chấm, bạn có thể làm hỏng một đường ống dẫn đến lỗi ... nhưng bạn có thể chuyển hướng bởi một dấu hai chấm, hoặc bỏ một quá trình với nó ... :| while i>&$(($??!$?:${#?})) command shit; do [ -s testitsoutput ]; done
hoặc tuy nhiên đề xuất giả đó được áp dụng ... ngoài ra, bạn có biết bạn cũng gần như ma như tôi không? ... tránh bằng mọi giá< <(psycho shit i can alias to crazy math eat your world; okay? anyway, ksh93 has a separate but equal composite char placement)
split
có khác (bị phản đối, nhưng không ai quan tâm) Cú pháp để tách đầu vào thành phần của N
dòng, mỗi dòng: thay vì split -lN
bạn có thể sử dụng split -N
ví dụ split -9
.
Về cơ bản, shell là một loại ngôn ngữ vĩ mô, hoặc ít nhất là một loại lai hoặc một loại nào đó. Mỗi dòng lệnh về cơ bản có thể được chia thành hai phần: phần phân tích / đầu vào và phần mở rộng / đầu ra.
Phần đầu tiên là những gì hầu hết mọi người tập trung vào vì nó đơn giản nhất: bạn thấy những gì bạn nhận được. Phần thứ hai là điều mà nhiều người tránh thậm chí cố gắng hiểu rất rõ và đó là lý do tại sao mọi người nói những điều như eval
là xấu xa và luôn trích dẫn những mở rộng của bạn - mọi người muốn kết quả của phần đầu tiên bằng với phần đầu tiên. Điều đó ổn - nhưng nó dẫn đến các nhánh mã dài không cần thiết và hàng tấn thử nghiệm ngoại lai.
Mở rộng là tự kiểm tra . Các ${param[[:]#%+-=?]word}
biểu mẫu là quá đủ để xác thực nội dung của một tham số, có thể lồng nhau và tất cả đều dựa trên việc đánh giá NUL - đó là điều mà hầu hết mọi người mong đợi về các bài kiểm tra. +
có thể đặc biệt tiện dụng trong các vòng lặp:
r()while IFS= read -r r&&"${r:+set}" -- "$@" "${r:=$*}";do :;done 2>&-
IFS=x
printf %s\\n some lines\ of input here '' some more|{ r;echo "$r"; }
somexlines ofxinputxhere
... Trong khi read
kéo vào các dòng không trống "${r:+set}"
sẽ mở rộng ra "set"
và các vị trí được $r
nối thêm. Nhưng khi một dòng trống read
, $r
trống và "${r:+set}"
mở rộng thành ""
- đó là một lệnh không hợp lệ. Nhưng vì các dòng lệnh được mở rộng trước khi các ""
lệnh null được tìm kiếm, "${r:=$*}"
mất các giá trị của tất cả các positionals nối trên byte đầu tiên trong $IFS
là tốt. r()
cũng có thể được gọi lại trong |{
lệnh ghép ;}
w / một giá trị khác $IFS
để có được đoạn đầu vào tiếp theo, vì việc shell của read
bộ đệm nằm ngoài \n
ewline tiếp theo trong đầu vào là bất hợp pháp .
Sử dụng đệ quy đuôi để làm cho các vòng lặp ngắn hơn:
Đây là tương đương trong hành vi (mặc dù có thể không sử dụng bộ nhớ / PID):
while :;do body; done
f()(body;f);f
body;exec $0
body;$0
Và những thứ này tương đương nhau:
while condition; do body; done
f()(body;condition&&f);f
body;condition&&exec $0
body;condition&&$0
(về mặt kỹ thuật, ba người cuối cùng sẽ luôn thực hiện cơ thể ít nhất một lần)
Việc sử dụng $0
yêu cầu tập lệnh của bạn nằm trong một tệp, không được dán vào dấu nhắc bash.
Cuối cùng, ngăn xếp của bạn có thể tràn, nhưng bạn lưu một số byte.
Đôi khi nó ngắn hơn để sử dụng expr
nội dung để hiển thị kết quả của biểu thức số học đơn giản thay vì thông thường echo $[ ]
. Ví dụ:
expr $1 % 2
ngắn hơn một byte so với:
echo $[$1%2]
pwd
thay vì echo
để tạo ra một dòng đầu raCần đặt một dòng trên thiết bị xuất chuẩn nhưng không quan tâm đến nội dung và muốn hạn chế câu trả lời của bạn đối với nội dung shell? pwd
là một byte ngắn hơn echo
.
Báo giá có thể được bỏ qua khi in chuỗi.
echo "example"
echo example
Đầu ra trong SM-T335 LTE, Android 5.1.1:
u0_a177@milletlte:/ $ echo "example"
example
u0_a177@milletlte:/ $ echo example
example
Khi gán các mục mảng không liên tục, bạn vẫn có thể bỏ qua các chỉ số liên tiếp của các khối liên tục:
bash-4.4$ a=([1]=1 [2]=2 [3]=3 [21]=1 [22]=2 [23]=3 [31]=1)
bash-4.4$ b=([1]=1 2 3 [21]=1 2 3 [31]=1)
Kết quả là như nhau:
bash-4.4$ declare -p a b
declare -a a=([1]="1" [2]="2" [3]="3" [21]="1" [22]="2" [23]="3" [31]="1")
declare -a b=([1]="1" [2]="2" [3]="3" [21]="1" [22]="2" [23]="3" [31]="1")
Theo man bash
:
Mảng được gán để sử dụng các phép gán ghép của tên biểu mẫu = (giá trị 1 ... giá trị n ), trong đó mỗi giá trị có dạng [ subscript ] = chuỗi . Bài tập mảng được lập chỉ mục không yêu cầu gì ngoài chuỗi . Khi gán cho các mảng được lập chỉ mục, nếu dấu ngoặc và chỉ mục tùy chọn được cung cấp, chỉ mục đó được gán cho; mặt khác, chỉ mục của phần tử được gán là chỉ mục cuối cùng được gán bởi câu lệnh cộng với một.
Nếu chuỗi nằm trong biến a
và không chứa ký tự thoát và định dạng ( \
và %
), hãy sử dụng:
printf $a
Nhưng nó sẽ dài hơn đoạn mã sau nếu cần lưu kết quả vào một biến thay vì in:
x=($a)
$x
Nếu bạn muốn gán một chuỗi được trích dẫn cho một biến, sau đó in giá trị của biến đó, thì cách thông thường để làm điều đó sẽ là:
a="Programming Puzzles & Code Golf";echo $a
Nếu a
trước đây không được đặt, điều này có thể được rút ngắn thành:
echo ${a=Programming Puzzles & Code Golf}
Nếu a
đã được đặt trước đó, thì cái này nên được sử dụng thay thế:
echo ${a+Programming Puzzles & Code Golf}
Lưu ý rằng điều này chỉ hữu ích nếu chuỗi yêu cầu dấu ngoặc kép (ví dụ chứa khoảng trắng). Không có trích dẫn, a=123;echo $a
chỉ là ngắn.
${a+foo}
không được thiết lập a
.
sh
và shell nào cho phépfor
cú pháp này ? nó được cho phép rõ ràng trongzsh
.