Друк масиву у файл з кожним елементом масиву в новому рядку в bash


13

Я намагаюся вміст масиву у файлі з кожним елементом масиву в новому рядку у файлі.

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


Зміст mtches - "qwe" та "asd". Але sample1.txtфайл містить qwe asdв одному рядку. Чому він не приймає значення IFS до зображення?

Відповіді:


17

Ви повинні використовувати printfзамістьecho :

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

Якщо mtchesпорожній, він все одно виведе один порожній рядок. Для обліку цього:

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

У bash(а також оболонках POSIX) ви часто використовуєте масив позиційних параметрів як "$@"замість них "$*", якщо у вас немає особливих причин. Це також стосується оболонок, які підтримують регулярні масиви, від man bash - розділ масиви :

На будь-який елемент масиву можна посилатися, використовуючи $ {name [subscript]}. Дужки потрібні, щоб уникнути конфліктів з операторами розширення імені файлу оболонки. Якщо в індексі "@" або "*", слово розширюється на всі члени імені масиву. Ці підписки відрізняються лише тоді, коли слово з’являється в подвійних лапках. Якщо слово подвійне цитування, $ {name [*]} розширюється до одного слова зі значенням кожного члена масиву, розділеного першим символом змінної IFS, а $ {name [@]} розширює кожен елемент імені до окремого слова. Коли немає членів масиву, $ {name [@]} розширюється до нічого. Якщо розширення з подвійним цитуванням відбувається в межах слова, розширення першого параметра з'єднується з початковою частиною вихідного слова, а розширення останнього параметра з'єднується з останньою частиною вихідного слова.

Використовуйте лише "${array[*]}"тоді, коли ви хочете приєднати всі елементи масиву до рядка.


Як це робить різницю?
Ешвін


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 -e "${alpha[@]}"

1
for ENTRY in ${ARRAY[@]}; do
    echo $ENTRY
done > outfile

Приємно і читати і не означає возитися з IFS. Це також означає, що ви можете налаштувати обробку кожного рядка.


1
Але неправильно, оскільки ви використовуєте, echoякий не можна використовувати для довільного вмісту, і забули процитувати ваші змінні . Трохи кращу версію вже опублікував СтівенПенні
Stéphane Chazelas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.