หากฉันมีอาร์เรย์เช่นนี้ใน Bash:
FOO=( a b c )
ฉันจะเข้าร่วมองค์ประกอบด้วยเครื่องหมายจุลภาคได้อย่างไร a,b,c
ยกตัวอย่างเช่นการผลิต
หากฉันมีอาร์เรย์เช่นนี้ใน Bash:
FOO=( a b c )
ฉันจะเข้าร่วมองค์ประกอบด้วยเครื่องหมายจุลภาคได้อย่างไร a,b,c
ยกตัวอย่างเช่นการผลิต
คำตอบ:
โซลูชันการเขียนซ้ำโดย Pascal Pilz เป็นฟังก์ชันใน 100% pure Bash (ไม่มีคำสั่งภายนอก):
function join_by { local IFS="$1"; shift; echo "$*"; }
ตัวอย่างเช่น,
join_by , a "b c" d #a,b c,d
join_by / var local tmp #var/local/tmp
join_by , "${FOO[@]}" #a,b,c
หรือเราสามารถใช้ printf เพื่อรองรับตัวคั่นหลายตัวโดยใช้แนวคิดโดย @gniourf_gniourf
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
ตัวอย่างเช่น,
join_by , a b c #a,b,c
join_by ' , ' a b c #a , b , c
join_by ')|(' a b c #a)|(b)|(c
join_by ' %s ' a b c #a %s b %s c
join_by $'\n' a b c #a<newline>b<newline>c
join_by - a b c #a-b-c
join_by '\' a b c #a\b\c
konsolebox
รูปแบบ :) หรือfunction join { local IFS=$1; __="${*:2}"; }
function join { IFS=$1 eval '__="${*:2}"'; }
จากนั้นใช้__
หลังจาก ใช่ฉันเป็นคนหนึ่งที่ส่งเสริมการใช้__
เป็นตัวแปรผลลัพธ์;) (และตัวแปรการทำซ้ำทั่วไปหรือตัวแปรชั่วคราว) หากแนวคิดได้รับความนิยมจากเว็บไซต์วิกิพีเดียทุบตีพวกเขาคัดลอกฉัน :)
$d
printf
คุณคิดว่าคุณปลอดภัยเพราะคุณ“ หลบหนี” %
แต่มีข้อแม้อื่น ๆ : เมื่อตัวคั่นประกอบด้วยเครื่องหมายแบ็กสแลช (เช่น\n
) หรือเมื่อตัวคั่นเริ่มต้นด้วยเครื่องหมายยัติภังค์ แน่นอนว่าคุณสามารถแก้ไขสิ่งเหล่านี้ได้ (แทนที่แบ็กสแลชโดยใช้แบ็กสแลชคู่และใช้printf -- "$d%s"
) แต่ในบางจุดคุณจะรู้สึกว่าคุณกำลังต่อสู้กับเชลล์แทนที่จะทำงานกับมัน นั่นเป็นเหตุผลว่าทำไมในคำตอบของฉันด้านล่างฉันได้เตรียมตัวคั่นกับข้อกำหนดที่จะเข้าร่วม
อีกวิธีหนึ่ง:
#!/bin/bash
foo=('foo bar' 'foo baz' 'bar baz')
bar=$(printf ",%s" "${foo[@]}")
bar=${bar:1}
echo $bar
แก้ไข: เหมือนกัน แต่สำหรับตัวคั่นความยาวตัวแปรหลายตัว:
#!/bin/bash
separator=")|(" # e.g. constructing regex, pray it does not contain %s
foo=('foo bar' 'foo baz' 'bar baz')
regex="$( printf "${separator}%s" "${foo[@]}" )"
regex="${regex:${#separator}}" # remove leading separator
echo "${regex}"
# Prints: foo bar)|(foo baz)|(bar baz
printf -v bar ",%s" "${foo[@]}"
สิ่งที่เกี่ยวกับ มันfork
น้อยกว่า (จริง ๆclone
) printf -v bar ",%s" $(<infile)
แม้มันเป็นฟอร์กอ่านไฟล์:
$separator
ไม่ได้มี%s
หรือเช่นคุณสามารถทำให้คุณแข็งแกร่ง:printf
printf "%s%s" "$separator" "${foo[@]}"
printf "%s%s"
จะใช้คั่นในกรณีแรกการตั้งค่าเฉพาะของการส่งออกและจากนั้นก็เชื่อมส่วนที่เหลือของการขัดแย้ง.
printf "%s" "${foo[@]/#/$separator}"
แต่ผมจะแนะนำสิ่งที่ต้องการ
IFS=; regex="${foo[*]/#/$separator}"
ซ้ำซ้อนและสายที่สามารถจะลดลงไป ณ จุดนี้สิ่งนี้กลายเป็นคำตอบของ gniourf_gniourf ซึ่ง IMO นั้นสะอาดกว่าตั้งแต่เริ่มต้นนั่นคือการใช้ฟังก์ชั่นเพื่อ จำกัด ขอบเขตการเปลี่ยนแปลงของ IFS และ temp vars
$ foo=(a "b c" d)
$ bar=$(IFS=, ; echo "${foo[*]}")
$ echo "$bar"
a,b c,d
bar=$( IFS=, ; echo "${foo[*]}" )
@
แทน*
ในขณะที่$(IFS=, ; echo "${foo[@]}")
? ฉันจะเห็นว่า*
ช่องว่างที่เก็บรักษาไว้ในองค์ประกอบแล้วไม่แน่ใจว่าเพราะ@
ปกติแล้วเป็นสิ่งที่จำเป็น
*
คำตอบก็คือไอเอฟเอได้รับการยอมรับเฉพาะสำหรับ ในหน้า bash man ให้ค้นหา "พารามิเตอร์พิเศษ" แล้วมองหาคำอธิบายถัดจาก*
:
อาจจะเช่น
SAVE_IFS="$IFS"
IFS=","
FOOJOIN="${FOO[*]}"
IFS="$SAVE_IFS"
echo "$FOOJOIN"
echo "-${IFS}-"
(วงเล็บปีกกาแยกเส้นประออกจากชื่อตัวแปร)
echo $IFS
จะเป็นสิ่งเดียวกัน.
น่าแปลกที่โซลูชันของฉันยังไม่ได้รับ :) นี่เป็นวิธีที่ง่ายที่สุดสำหรับฉัน ไม่ต้องการฟังก์ชั่น:
IFS=, eval 'joined="${foo[*]}"'
หมายเหตุ: วิธีแก้ปัญหานี้ตรวจพบว่าทำงานได้ดีในโหมดที่ไม่ใช่ POSIX ในโหมด POSIXองค์ประกอบจะยังคงเข้าร่วมอย่างถูกต้อง แต่IFS=,
กลายเป็นแบบถาวร
นี่คือฟังก์ชั่น pure Bash 100% ที่ทำงาน:
join() {
# $1 is return variable name
# $2 is sep
# $3... are the elements to join
local retname=$1 sep=$2 ret=$3
shift 3 || shift $(($#))
printf -v "$retname" "%s" "$ret${@/#/$sep}"
}
ดู:
$ a=( one two "three three" four five )
$ join joineda " and " "${a[@]}"
$ echo "$joineda"
one and two and three three and four and five
$ join joinedb randomsep "only one element"
$ echo "$joinedb"
only one element
$ join joinedc randomsep
$ echo "$joinedc"
$ a=( $' stuff with\nnewlines\n' $'and trailing newlines\n\n' )
$ join joineda $'a sep with\nnewlines\n' "${a[@]}"
$ echo "$joineda"
stuff with
newlines
a sep with
newlines
and trailing newlines
$
สิ่งนี้จะรักษาแม้กระทั่งบรรทัดใหม่ต่อท้ายและไม่จำเป็นต้องมี subshell เพื่อรับผลลัพธ์ของฟังก์ชัน หากคุณไม่ชอบprintf -v
(ทำไมคุณไม่ชอบมัน) และผ่านชื่อตัวแปรคุณสามารถใช้ตัวแปรโกลบอลสำหรับสตริงที่ส่งคืน:
join() {
# $1 is sep
# $2... are the elements to join
# return is in global variable join_ret
local sep=$1 IFS=
join_ret=$2
shift 2 || shift $(($#))
join_ret+="${*/#/$sep}"
}
join_ret
ตัวแปรเฉพาะที่จากนั้นจึงสะท้อนออกมาในตอนท้าย วิธีนี้ทำให้สามารถใช้ join () ในวิธีการเขียนสคริปต์เชลล์ปกติเช่น$(join ":" one two three)
และไม่จำเป็นต้องใช้ตัวแปรโกลบอล
$(...)
จดจ้องขึ้นบรรทัดใหม่ ดังนั้นหากฟิลด์สุดท้ายของอาเรย์มีการขึ้นบรรทัดใหม่ต่อท้ายสิ่งเหล่านี้จะถูกตัดแต่ง (ดูตัวอย่างที่ไม่ได้ถูกตัดแต่งด้วยการออกแบบของฉัน)
สิ่งนี้ไม่ได้แตกต่างจากโซลูชันที่มีอยู่ทั้งหมด แต่หลีกเลี่ยงการใช้ฟังก์ชั่นแยกต่างหากไม่ได้แก้ไขIFS
ในเชลล์พาเรนต์และทั้งหมดในบรรทัดเดียว:
arr=(a b c)
printf '%s\n' "$(IFS=,; printf '%s' "${arr[*]}")"
ที่เกิดขึ้นใน
a,b,c
ข้อ จำกัด : ตัวคั่นต้องไม่ยาวเกินหนึ่งอักขระ
ใช้ไม่มีคำสั่งภายนอก:
$ FOO=( a b c ) # initialize the array
$ BAR=${FOO[@]} # create a space delimited string from array
$ BAZ=${BAR// /,} # use parameter expansion to substitute spaces with comma
$ echo $BAZ
a,b,c
คำเตือนสันนิษฐานว่าองค์ประกอบไม่มีช่องว่าง
echo ${FOO[@]} | tr ' ' ','
ฉันจะสะท้อนอาร์เรย์เป็นสตริงแล้วแปลงช่องว่างเป็นตัวดึงข้อมูลบรรทัดแล้วใช้paste
เพื่อรวมทุกอย่างในหนึ่งบรรทัดดังนี้:
tr " " "\n" <<< "$FOO" | paste -sd , -
ผล:
a,b,c
นี่เป็นสิ่งที่เร็วและสะอาดสำหรับฉัน!
$FOO
เป็นเพียงองค์ประกอบแรกของอาเรย์ นอกจากนี้ยังแบ่งองค์ประกอบอาร์เรย์ที่มีช่องว่าง
ด้วยการนำกลับมาใช้ใหม่ของ @ ไม่สำคัญสำหรับการแก้ปัญหา แต่ด้วยคำสั่งเดียวโดยหลีกเลี่ยงสเตจย่อย $ {: 1} และต้องการตัวแปรตัวกลาง
echo $(printf "%s," "${LIST[@]}" | cut -d "," -f 1-${#LIST[@]} )
printf มี 'สตริงรูปแบบที่นำมาใช้ซ้ำได้บ่อยเท่าที่จำเป็นเพื่อตอบสนองข้อโต้แย้ง' ใน man man ของมันเพื่อที่ว่าเอกสารจะถูกต่อกัน จากนั้นเคล็ดลับคือการใช้ความยาว LIST เพื่อสับ sperator สุดท้ายเนื่องจากการตัดจะเก็บเฉพาะความยาวของ LIST ตามจำนวนฟิลด์
s=$(IFS=, eval 'echo "${FOO[*]}"')
@Q
สามารถหลีกเลี่ยงค่าการเข้าร่วมจากการตีความผิดเมื่อพวกเขามีผู้เข้าร่วมในพวกเขา: foo=("a ," "b ' ' c" "' 'd e" "f " ";" "ls -latr"); s=$(IFS=, eval 'echo "${foo[*]@Q}"'); echo "${s}"
ผลลัพธ์'a ,','b '\'' '\'' c',''\'' '\''d e','f ',';','ls -latr '
โซลูชัน printf ที่ยอมรับตัวคั่นความยาวเท่าใดก็ได้ (ตาม @ ไม่สำคัญกับคำตอบ)
#/!bin/bash
foo=('foo bar' 'foo baz' 'bar baz')
sep=',' # can be of any length
bar=$(printf "${sep}%s" "${foo[@]}")
bar=${bar:${#sep}}
echo $bar
printf
ระบุรูปแบบใด ๆ(เช่น%s
โดยไม่ได้ตั้งใจ$sep
จะทำให้เกิดปัญหา
sep
${sep//\%/%%}
สามารถปรุงแต่งด้วย ฉันชอบทางออกของคุณดีกว่า${bar#${sep}}
หรือ${bar%${sep}}
(ทางเลือก) นี้เป็นสิ่งที่ดีถ้าแปลงเป็นฟังก์ชั่นที่ร้านค้าส่งผลให้ตัวแปรทั่วไปเช่น__
และไม่echo
มัน
function join_by { printf -v __ "${1//\%/%%}%s" "${@:2}"; __=${__:${#1}}; }
$ set a 'b c' d
$ history -p "$@" | paste -sd,
a,b c,d
HISTSIZE=0
?
paste -sd,
ไม่ได้เกี่ยวกับการใช้ประวัติศาสตร์
HISTSIZE=0
ลองใช้ดู
เวอร์ชันสั้นกว่าของคำตอบยอดนิยม:
joinStrings() { local a=("${@:3}"); printf "%s" "$2${a[@]/#/$1}"; }
การใช้งาน:
joinStrings "$myDelimiter" "${myArray[@]}"
join_strings () { local d="$1"; echo -n "$2"; shift 2 && printf '%s' "${@/#/$d}"; }
join_strings () { local d="$1"; echo -n "$2"; shift 2 && printf '$d%s' "${@}"; }
ใช้งานได้กับการใช้งาน: join_strings 'delim' "${array[@]}"
หรือjoin_strings 'delim' ${array[@]}
รวมที่ดีที่สุดของโลกทั้งหมดจนถึงกับแนวคิดต่อไปนี้
# join with separator
join_ws() { local IFS=; local s="${*/#/$1}"; echo "${s#"$1$1$1"}"; }
ผลงานชิ้นเอกชิ้นนี้คือ
ตัวอย่าง:
$ join_ws , a b c
a,b,c
$ join_ws '' a b c
abc
$ join_ws $'\n' a b c
a
b
c
$ join_ws ' \/ ' A B C
A \/ B \/ C
join_ws ,
(มีข้อโต้แย้งไม่ได้) ,,
อย่างไม่ยุติธรรมเอาท์พุท 2. join_ws , -e
ส่งผลอะไรผิดพลาด (นั่นเป็นเพราะคุณใช้ผิดecho
แทนที่จะใช้printf
) จริง ๆ แล้วฉันไม่รู้ว่าทำไมคุณโฆษณาถึงการใช้echo
แทนprintf
: echo
จะเสียชื่อเสียงและprintf
เป็นตัวที่แข็งแกร่ง
ตอนนี้ฉันกำลังใช้:
TO_IGNORE=(
E201 # Whitespace after '('
E301 # Expected N blank lines, found M
E303 # Too many blank lines (pep8 gets confused by comments)
)
ARGS="--ignore `echo ${TO_IGNORE[@]} | tr ' ' ','`"
ซึ่งใช้งานได้ แต่ (ในกรณีทั่วไป) จะแตกหักอย่างน่ากลัวหากองค์ประกอบอาเรย์มีช่องว่างอยู่ในนั้น
(สำหรับผู้ที่สนใจนี่เป็นสคริปต์ตัวหุ้มรอบpep8.py )
ARGS="--ignore $(echo "${TO_IGNORE[@]}" | tr ' ' ',')"
สมมติว่าคุณเป็นจริงโดยใช้ทุบตีนี้อาจจะทำงานได้ดีขึ้น: ผู้ประกอบการ$()
มีประสิทธิภาพมากกว่า backtics (อนุญาตการซ้อน$()
และ""
) การห่อ${TO_IGNORE[@]}
ด้วยเครื่องหมายคำพูดคู่ควรช่วยด้วย
ความพยายามของฉัน
$ array=(one two "three four" five)
$ echo "${array[0]}$(printf " SEP %s" "${array[@]:1}")"
one SEP two SEP three four SEP five
ใช้ Perl สำหรับตัวคั่นหลายตัว:
function join {
perl -e '$s = shift @ARGV; print join($s, @ARGV);' "$@";
}
join ', ' a b c # a, b, c
หรือในหนึ่งบรรทัด:
perl -le 'print join(shift, @ARGV);' ', ' 1 2 3
1, 2, 3
join
ชื่อจะขัดแย้งกับอึบ้างOS X
ฉันจะเรียกมันว่าconjoined
หรืออาจจะjackie_joyner_kersee
?
ขอบคุณ @gniourf_gniourf สำหรับความคิดเห็นโดยละเอียดเกี่ยวกับการรวมกันของโลกที่ดีที่สุด ขออภัยที่โพสต์โค้ดไม่ได้ออกแบบและทดสอบอย่างละเอียด นี่คือความพยายามที่ดีกว่า
# join with separator
join_ws() { local d=$1 s=$2; shift 2 && printf %s "$s${@/#/$d}"; }
ความงามตามแนวคิดนี้คือ
ตัวอย่างเพิ่มเติม:
$ join_ws '' a b c
abc
$ join_ws ':' {1,7}{A..C}
1A:1B:1C:7A:7B:7C
$ join_ws -e -e
-e
$ join_ws $'\033[F' $'\n\n\n' 1. 2. 3. $'\n\n\n\n'
3.
2.
1.
$ join_ws $
$
ในกรณีที่องค์ประกอบที่คุณต้องการเข้าร่วมไม่ใช่อาร์เรย์เพียงแค่สตริงคั่นด้วยช่องว่างคุณสามารถทำสิ่งนี้:
foo="aa bb cc dd"
bar=`for i in $foo; do printf ",'%s'" $i; done`
bar=${bar:1}
echo $bar
'aa','bb','cc','dd'
ตัวอย่างเช่นกรณีการใช้งานของฉันคือมีการส่งผ่านสตริงบางส่วนในเชลล์สคริปต์ของฉันและฉันจำเป็นต้องใช้สิ่งนี้เพื่อรันบนเคียวรี SQL:
./my_script "aa bb cc dd"
ใน my_script ฉันต้องทำ "SELECT * จากตาราง WHERE ชื่อ IN ('aa', 'bb', 'cc', 'dd') จากนั้นคำสั่งด้านบนจะมีประโยชน์
printf -v bar ...
แทนที่จะต้องเรียกใช้ลูป printf ใน subshell และจับเอาท์พุท
นี่คือเชลล์ที่รองรับ POSIX ส่วนใหญ่รองรับ:
join_by() {
# Usage: join_by "||" a b c d
local arg arr=() sep="$1"
shift
for arg in "$@"; do
if [ 0 -lt "${#arr[@]}" ]; then
arr+=("${sep}")
fi
arr+=("${arg}") || break
done
printf "%s" "${arr[@]}"
}
local
) เลย
การใช้ตัวแปรทางอ้อมเพื่ออ้างอิงโดยตรงกับอาเรย์ก็ใช้งานได้เช่นกัน การอ้างอิงที่มีชื่อยังสามารถใช้ได้ แต่ข้อมูลอ้างอิงนั้นมีให้ใน 4.3 เท่านั้น
ข้อดีของการใช้รูปแบบของฟังก์ชั่นนี้คือคุณสามารถมีตัวเลือกตัวคั่น (ค่าเริ่มต้นเป็นอักขระตัวแรกของค่าเริ่มต้นIFS
ซึ่งเป็นช่องว่างอาจทำให้มันเป็นสตริงว่างถ้าคุณต้องการ) และมันหลีกเลี่ยงการขยายค่าสองครั้ง เมื่อส่งผ่านเป็นพารามิเตอร์และที่สองเป็น"$@"
ภายในฟังก์ชั่น)
โซลูชันนี้ยังไม่ต้องการให้ผู้ใช้เรียกใช้ฟังก์ชันภายในการทดแทนคำสั่ง - ซึ่งจะเรียกเชลล์ย่อยเพื่อรับสตริงเข้าร่วมรุ่นที่กำหนดให้กับตัวแปรอื่น
function join_by_ref {
__=
local __r=$1[@] __s=${2-' '}
printf -v __ "${__s//\%/%%}%s" "${!__r}"
__=${__:${#__s}}
}
array=(1 2 3 4)
join_by_ref array
echo "$__" # Prints '1 2 3 4'.
join_by_ref array '%s'
echo "$__" # Prints '1%s2%s3%s4'.
join_by_ref 'invalid*' '%s' # Bash 4.4 shows "invalid*[@]: bad substitution".
echo "$__" # Prints nothing but newline.
รู้สึกอิสระที่จะใช้ชื่อที่สะดวกสบายมากขึ้นสำหรับฟังก์ชั่น
ใช้งานได้ตั้งแต่ 3.1 ถึง 5.0-alpha ตามที่สังเกต, การแปรผันของตัวแปรไม่เพียงทำงานกับตัวแปรเท่านั้น แต่ใช้กับตัวแปรอื่นด้วยเช่นกัน
พารามิเตอร์คือเอนทิตีที่เก็บค่า มันอาจเป็นชื่อตัวเลขหรือหนึ่งในตัวละครพิเศษที่แสดงด้านล่างภายใต้พารามิเตอร์พิเศษ ตัวแปรคือพารามิเตอร์ที่แสดงด้วยชื่อ
อาร์เรย์และองค์ประกอบอาร์เรย์ยังเป็นพารามิเตอร์ (เอนทิตีที่เก็บค่า) และการอ้างอิงไปยังอาร์เรย์เป็นการอ้างอิงทางเทคนิคกับพารามิเตอร์เช่นกัน และเหมือนพารามิเตอร์พิเศษ@
, array[@]
นอกจากนี้ยังทำให้การอ้างอิงที่ถูกต้อง
รูปแบบการขยายหรือเปลี่ยนแปลงที่เลือก (เช่นการขยายสตริงย่อย) ที่เบี่ยงเบนการอ้างอิงจากพารามิเตอร์ตัวเองไม่ทำงานอีกต่อไป
ใน Bash 5.0 รุ่นวางจำหน่ายการเปลี่ยนทิศทางตัวแปรเรียกว่าการขยายตัวทางอ้อมแล้วและพฤติกรรมของมันได้รับการบันทึกไว้ในคู่มืออย่างชัดเจนแล้ว:
หากอักขระตัวแรกของพารามิเตอร์คือเครื่องหมายอัศเจรีย์ (!) และพารามิเตอร์ไม่ใช่ nameref มันจะแนะนำระดับของการอ้อม Bash ใช้ค่าที่เกิดขึ้นโดยการขยายพารามิเตอร์ที่เหลือเป็นพารามิเตอร์ใหม่ สิ่งนี้จะถูกขยายและค่านั้นจะถูกใช้ในส่วนที่เหลือของการขยายตัวมากกว่าการขยายตัวของพารามิเตอร์เดิม สิ่งนี้เรียกว่าการขยายตัวทางอ้อม
การจดบันทึกว่าในเอกสารของ${parameter}
, parameter
จะเรียกว่า"พารามิเตอร์เปลือกตามที่อธิบายไว้ (ใน) พารามิเตอร์หรือการอ้างอิงอาร์เรย์ " และในเอกสารประกอบของอาร์เรย์มีการกล่าวถึงว่า"องค์ประกอบใด ๆ ของอาร์เรย์อาจถูกอ้างอิงโดยใช้${name[subscript]}
" สิ่งนี้ทำให้__r[@]
การอ้างอิงอาร์เรย์
ฉันในการแสดงความคิดเห็นในคำตอบของคาร์โด้ Galli
__
เป็นชื่อตัวแปรหรือไม่? ทำให้โค้ดอ่านไม่ได้จริงๆ
วิธีการนี้จะดูแลช่องว่างภายในค่า แต่ต้องการการวนซ้ำ:
#!/bin/bash
FOO=( a b c )
BAR=""
for index in ${!FOO[*]}
do
BAR="$BAR,${FOO[$index]}"
done
echo ${BAR:1}
ถ้าคุณสร้างอาเรย์ในวงนี่เป็นวิธีง่าย ๆ :
arr=()
for x in $(some_cmd); do
arr+=($x,)
done
arr[-1]=${arr[-1]%,}
echo ${arr[*]}
x=${"${arr[*]}"// /,}
นี่เป็นวิธีที่สั้นที่สุดที่จะทำ
ตัวอย่าง,
arr=(1 2 3 4 5)
x=${"${arr[*]}"// /,}
echo $x # output: 1,2,3,4,5
bash: ${"${arr[*]}"// /,}: bad substitution
อาจจะสายสำหรับปาร์ตี้ แต่สิ่งนี้ใช้ได้สำหรับฉัน:
function joinArray() {
local delimiter="${1}"
local output="${2}"
for param in ${@:3}; do
output="${output}${delimiter}${param}"
done
echo "${output}"
}
บางทีฉันอาจขาดอะไรบางอย่างที่เห็นได้ชัดเนื่องจากฉันเป็นมือใหม่ถึงสิ่งทุบตี / zsh ทั้งหมด แต่ดูเหมือนว่าฉันจะไม่ต้องการใช้printf
เลย และไม่น่าเกลียดที่จะทำโดยไม่ทำเช่นนั้น
join() {
separator=$1
arr=$*
arr=${arr:2} # throw away separator and following space
arr=${arr// /$separator}
}
อย่างน้อยมันก็ใช้ได้ผลสำหรับฉันจนถึงตอนนี้โดยไม่มีปัญหา
ตัวอย่างเช่นjoin \| *.sh
ที่ฉันว่าใน~
ไดเรกทอรีของฉันผลลัพธ์utilities.sh|play.sh|foobar.sh
ไดเรกทอรีเอาท์พุทดีพอสำหรับฉัน
แก้ไข: นี่คือคำตอบของ Nil Geisweillerแต่โดยทั่วไปเป็นฟังก์ชั่น
liststr=""
for item in list
do
liststr=$item,$liststr
done
LEN=`expr length $liststr`
LEN=`expr $LEN - 1`
liststr=${liststr:0:$LEN}
นี้จะดูแลเครื่องหมายจุลภาคพิเศษในตอนท้ายด้วย ฉันไม่มีผู้เชี่ยวชาญทุบตี แค่ 2c ของฉันเนื่องจากนี่เป็นระดับประถมศึกษาและเข้าใจได้ง่ายขึ้น
awk -v sep=. 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"
หรือ
$ a=(1 "a b" 3)
$ b=$(IFS=, ; echo "${a[*]}")
$ echo $b
1,a b,3