44

Я хочу записать переменную массива bash в файл, с каждым элементом в новой строке. Я мог бы сделать это с помощью цикла for, но есть ли другой (более чистый) способ объединения элементов с помощью \n?

6 ответов6

49

Вот способ, который использует расширение параметра bash и его специальную переменную IFS .

$ System=('s1' 's2' 's3' 's4 4 4')
$ ( IFS=$'\n'; echo "${System[*]}" )

Мы используем подоболочку, чтобы избежать перезаписи значения IFS в текущей среде. В этой подоболочке мы затем модифицируем значение IFS чтобы первый символ был новой строкой (с использованием кавычек $'...' ). Наконец, мы используем расширение параметра, чтобы напечатать содержимое массива как одно слово; каждый элемент отделен первым символом IFS .

Для захвата в переменную:

$ var=$( IFS=$'\n'; echo "${System[*]}" )

Если ваш bash достаточно новый (4.2 или более поздний), вы можете (и должны) по-прежнему использовать printf с опцией -v :

$ printf -v var "%s\n" "${System[@]}"

В любом случае, вам может не потребоваться заключительный перевод строки в var . Чтобы удалить это:

$ var=${var%?}    # Remove the final character of var
25

Вы можете использовать printf для печати каждого элемента массива в отдельной строке:

 $ System=('s1' 's2' 's3' 's4 4 4')
 $ printf "%s\n"  "${System[@]}"
s1
s2
s3
s4 4 4
6
awk -v sep='\n' 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"

или же

perl -le 'print join "\n",@ARGV' "${arr[@]}"

или же

python -c 'import sys;print "\n".join(sys.argv[1:])' "${arr[@]}"

или же

sh -c 'IFS=$'\''\n'\'';echo "$*"' '' "${arr[@]}"

или же

lua <(echo 'print(table.concat(arg,"\n"))') "${arr[@]}"

или же

tclsh <(echo 'puts [join $argv "\n"]') "${arr[@]}"

или же

php -r 'echo implode("\n",array_slice($argv,1));' -- "${arr[@]}"

или же

ruby -e 'puts ARGV.join("\n")' "${arr[@]}"

это все, что я могу напомнить до сих пор.

2

Приведенные выше решения в значительной степени таковы, но исходный вопрос требует вывода в файл:

$ a=(a b c d e)
$ ( IFS=$'\n'; echo "${a[*]}" ) > /tmp/file
$ cat /tmp/file
a
b
c
d
e
$

Примечания:1) 'echo' предоставляет последний символ новой строки. 2) Если этот файл просто будет снова прочитан bash, тогда можно объявить -p желаемой сериализацией.

2

Использование для:

for each in "${alpha[@]}"
do
  echo "$each"
done

Использование истории ; обратите внимание, что это не удастся, если ваши значения содержат !:

history -p "${alpha[@]}"

Использование базового имени ; обратите внимание, что это не удастся, если ваши значения содержат /:

basename -a "${alpha[@]}"

Использование shuf ; обратите внимание, что результаты могут быть не в порядке:

shuf -e "${alpha[@]}"
-1

printf представляется наиболее эффективным подходом для создания строки с разделителями из массива:

# create a delimited string; note that printf doesn't put the trailing delimiter
# need to save and restore IFS
# it is prudent to put the whole logic on a single line so as to minimize the risk of future code changes breaking the sequence of saving/restoring of IFS
oldIFS=$IFS; IFS=$'\n'; printf -v var "${arr[*]}"; IFS=$oldIFS

# print string to file; note that the newline is required in the format string because printf wouldn't put a trailing delimiter (which is a good thing)
printf '%s\n' "$var" > file

Еще более простой способ сделать это:

delim=$'\n'
printf -v var "%s$delim" "${arr[@]}" # create a delimited string
var="${var%$delim}"                  # remove the trailing delimiter

пример

delim=:
arr=(one two three)
printf -v var "%s$delim" "${arr[@]}" # yields one:two:three:
var="${var%$delim}"                  # yields one:two_three

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .