Печать массива в файл с каждым элементом массива в новой строке в bash

13

Я пытаюсь содержимое массива в файл с каждым элементом массива в новой строке в файле.

IFS=$'\n'   
echo "${mtches[@]}" > sample1.txt 


Содержимое mtches - "qwe" и "asd". Но sample1.txtфайл содержится qwe asdв одной строке. Почему это не берет значение IFS в картину?

Ashwin
источник

Ответы:

17

Вы должны использовать printfвместоecho :

printf "%s\n" "${mtches[@]}"

Если mtchesпусто, то все равно выведите одну пустую строку. Чтобы учесть это:

{ [ "${#mtches[@]}" -eq 0 ] || printf '%s\n' "${mtches[@]}"; } > file

В bash(а также POSIX оболочек), часто используются позиционные параметры массива , как "$@"вместо того , чтобы "$*", если у вас нет особых причин. Это также верно для оболочек, поддерживающих обычные массивы, из man bash - section Arrays :

На любой элемент массива можно ссылаться, используя $ {name [subscript]}. Скобки необходимы, чтобы избежать конфликтов с операторами расширения имени оболочки. Если нижний индекс равен «@» или «*», слово распространяется на все члены имени массива. Эти индексы отличаются только тогда, когда слово появляется в двойных кавычках. Если слово заключено в двойные кавычки, $ {name [*]} раскрывается в одно слово, в котором значение каждого члена массива отделяется первым символом переменной IFS, а $ {name [@]} раскрывает каждый элемент имени в отдельном слове. Когда нет элементов массива, $ {name [@]} расширяется до нуля. Если раскрытие в двойных кавычках происходит внутри слова, расширение первого параметра объединяется с начальной частью исходного слова, а расширение последнего параметра объединяется с последней частью исходного слова.

Используйте только "${array[*]}"тогда, когда вы хотите объединить все элементы массива в строку.

cuonglm
источник
Как это сделать разницу?
Эшвин
7

Вы хотите использовать ${mtches[*]}вместо этого.

Когда вы используете "${mtches[@]}", значение не имеет значения $IFS, bash разделит массив на несколько аргументов. То, что вы хотите, это один аргумент, к которому присоединяется каждый элемент массива \n. ${mtches[*]}выполняет это.

Также в качестве временного способа настройки $IFSвы можете сделать:

( IFS=$'\n'; echo "${mtches[*]}" > sample1.txt )

Тогда вам не нужно беспокоиться об установке обратно.

Патрик
источник
pubs.opengroup.org/onlinepubs/9699919799/utilities/… <- ссылка на POSIX (это относится не только к bash).
Мат
Или используйте printf...
jasonwryan
2

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

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

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

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

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

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

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

shuf -e "${alpha[@]}"
Стивен Пенни
источник
1
for ENTRY in ${ARRAY[@]}; do
    echo $ENTRY
done > outfile

Красиво и читабельно и не значит возиться с IFS. Это также означает, что вы можете настроить обработку каждой строки.

steveayre
источник
1
Но неправильно, так как вы используете, echoкоторый не может быть использован для произвольного контента и забыл процитировать ваши переменные . Немного лучшая версия уже была опубликована StevenPenny
Стефаном