14

I am trying the contents of an array into a file with each element of the array in a new line in the file.

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


The content of mtches is "qwe" and " asd". But the sample1.txt file contains qwe asd in a single line. Why is it not taking IFS value into the picture?

20

You should use printf instead of echo:

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

If mtches is empty that would still output one empty line. To account for that:

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

In bash (and also POSIX shells), you often use Positional Parameters array as"$@" instead of "$*", unless you have a special reason. That's also true in shells that support regular arrays, from man bash - section Arrays:

Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with the shell’s filename expansion operators. If the subscript is ‘@’ or ‘*’, the word expands to all members of the array name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS variable, and ${name[@]} expands each element of name to a separate word. When there are no array members, ${name[@]} expands to nothing. If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. This is analogous to the expansion of the special parameters ‘@’ and ‘*’

Only use "${array[*]}" when you want join all array elements to a string.

2
7

You want to use ${mtches[*]} instead.

When you use "${mtches[@]}", it doesn't matter what the value of $IFS is, bash will split the array into multiple arguments. What you want is a single argument with each array element joined by \n. ${mtches[*]} accomplishes this.

Also as a temporary way of setting $IFS, you can do:

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

Then you don't have to bother with setting it back.

2
2

Using for:

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

Using history; note this will fail if your values contain !:

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

Using basename; note this will fail if your values contain /:

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

Using shuf; note that results might not come out in order:

shuf -e "${alpha[@]}"
1
for ENTRY in ${ARRAY[@]}; do
    echo $ENTRY
done > outfile

Nice and readable and doesn't mean messing with IFS. It also means you can customise the handling of each line.

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.