Объединение строк с помощью делиметра в цикле for в скрипте оболочки

#bash #shell #git-bash

Вопрос:

Добавление запятой создает пробел вместо добавления запятой.

Примечание: Значение $1 is s,v,h

 declare -A handles
handles["s"]="test1"
handles["v"]="test2"
handles["h"]="test3"

IFS=',' list=($1)
for item in "${list[@]}"; do
        result =",${handles["$item"]}"
done

echo -e $result
 

Выход: test1 test2 test3

Ожидаемый: test1,test2,test3

Комментарии:

1. @markp-Значение fuso $1 равно s,v,h

2. IFS=',' list=($1) не выполняет list задание с помощью IFS, установленного в его среде. Вместо этого он эквивалентен IFS=','; list=($1); , таким образом , действуя как два задания. Я бы сказал, что основная проблема заключается в отсутствии кавычек в echo , что и должно быть echo -e "$result" , но сброс IFS до разумного значения, безусловно, хорошая идея.

Ответ №1:

Одна идея , чтобы обойти проблемы с блокировкой IFS и устранением нежелательных запятых из $result , …

 $ cat script.sh
#!/usr/bin/bash

declare -A handles
handles["s"]="test1"
handles["v"]="test2"
handles["h"]="test3"
handles["a b c"]="test 4"

mapfile -t list < <(tr ',' 'n' <<< "$1")     # to handle white space in fields

unset pfx

for item in "${list[@]}"
do
    handle="${handles[$item]}"

    # only append if non-empty
    [ -n "${handle}" ] amp;amp; result ="${pfx}${handle}" amp;amp; pfx=','
done

echo -e "${result}"

$ script.sh 's,v,h'
test1,test2,test3

$ script.sh 'a b c,s,v,h'
test 4,test1,test2,test3

$ script.sh 'd e f,s,v,h'
test1,test2,test3

$ script.sh 'x,y,z,s,v,h,a,b,c'
test1,test2,test3
 

Ответ №2:

В IFS чем проблема:

 > x=",a" amp;amp; x =",b" amp;amp; x =",c" amp;amp; echo $x
,a,b,c 
> IFS="," amp;amp; x=",a" amp;amp; x =",b" amp;amp; x =",c" amp;amp; echo $x
 a b c
 

Просто добавьте IFS="" перед echo использованием echo -e "$result" операции, и это сработает.

Комментарии:

1. Это один из способов увидеть это. С моей точки зрения, без кавычек $result -это проблема и нет IFS .

Ответ №3:

Я предполагаю, что вы хотите временно назначить IFS «,», чтобы не влиять на следующие коды. Затем вы можете объединить его с read командой следующим образом:

 #!/bin/bash

declare -A handles=(
    ["s"]="test1"
    ["v"]="test2"
    ["h"]="test3"
)

IFS=',' read -r -a list <<< "$1"
for item in "${list[@]}"; do
    ary =( "${handles["$item"]}" )
done

result=$(IFS=','; echo "${ary[*]}")
echo "$result"
 
  • for Цикл присваивает массиву ary значения ассоциативного массива handles , к которому относятся элементы list .
  • Команда echo "${ary[*]}" объединяет массив ary с разделителем , . Он выполняется во вложенной оболочке без изменений IFS в процессе переднего плана.