Thủ thuật một dòng đơn giản để đổ mảng
Tôi đã thêm một giá trị với khoảng trắng:
foo=()
foo[12]="bar"
foo[42]="foo bar baz"
foo[35]="baz"
Tôi, để nhanh chóng đổ bashmảng hoặc mảng kết hợp tôi sử dụng
Lệnh một dòng này:
paste <(printf "%s\n" "${!foo[@]}") <(printf "%s\n" "${foo[@]}")
Sẽ kết xuất:
12 bar
35 baz
42 foo bar baz
Giải thích
printf "%s\n" "${!foo[@]}"
sẽ in tất cả các khóa được phân tách bằng một dòng mới ,
printf "%s\n" "${foo[@]}"
sẽ in tất cả các giá trị được phân tách bằng một dòng mới ,
paste <(cmd1) <(cmd2)
sẽ hợp nhất đầu ra cmd1
và cmd2
theo từng dòng.
Điều chỉnh
Điều này có thể được điều chỉnh bằng -d
chuyển đổi:
paste -d : <(printf "%s\n" "${!foo[@]}") <(printf "%s\n" "${foo[@]}")
12:bar
35:baz
42:foo bar baz
hoặc thậm chí:
paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "'%s'\n" "${foo[@]}")
foo[12]='bar'
foo[35]='baz'
foo[42]='foo bar baz'
Mảng kết hợp sẽ hoạt động như nhau:
declare -A bar=([foo]=snoopy [bar]=nice [baz]=cool [foo bar]='Hello world!')
paste -d = <(printf "bar[%s]\n" "${!bar[@]}") <(printf '"%s"\n' "${bar[@]}")
bar[foo bar]="Hello world!"
bar[foo]="snoopy"
bar[bar]="nice"
bar[baz]="cool"
Vấn đề với dòng mới hoặc ký tự đặc biệt
Thật không may, có ít nhất một điều kiện làm cho điều này không hoạt động nữa: khi biến có chứa dòng mới:
foo[17]=$'There is one\nnewline'
Lệnh paste
sẽ hợp nhất từng dòng một, do đó đầu ra sẽ bị sai:
paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "'%s'\n" "${foo[@]}")
foo[12]='bar'
foo[17]='There is one
foo[35]=newline'
foo[42]='baz'
='foo bar baz'
Đối với công việc này, bạn có thể sử dụng %q
thay vì %s
trong printf
lệnh thứ hai (và trích dẫn whipe):
paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "%q\n" "${foo[@]}")
Sẽ hoàn hảo:
foo[12]=bar
foo[17]=$'There is one\nnewline'
foo[35]=baz
foo[42]=foo\ bar\ baz
Từ man bash
:
%q causes printf to output the corresponding argument in a
format that can be reused as shell input.
(a b c)
để chuyển đổi nó thành một mảng.