Space and Newline in Array(Shell script) - arrays

How to store space and Newline in array. Consider the following is my file.
a.txt:
this is file a.txt
for testing
and for checking
Now, I want to store each and every character in the file in each element of the array. Like 't' in arr[0], 'h' in arr[1], 'i' in arr[2], 's' in arr[3] and ' '(space) in arr[4] respectively. And If I print the content of array like ${a[*]}, the output is to be exact file content. So, is there any way to store space and newline in array.

You can use:
arr=()
while IFS= read -d '' -r -n1 c; do
arr+=("$c")
done < file
read -n1 will make this loop read the input character by character.
-d '' will make delimiter as null instead of newline
IFS= is needed to read leading or trailing spaces in each line.
Verify:
printf "%s" "${arr[#]}"
this is file a.txt
for testing
and for checking

Related

Creating an array from substrings in Bash not working [duplicate]

This question already has answers here:
Split string into array using multi-character delimiter
(5 answers)
Closed 2 years ago.
Why are the last two array elements being truncated?
I'm trying to generate an array from a string in bash, using a \n as the delaminating character. Using command substitution and tr I was close to what I wanted, now I'm getting strange output.
Script file below
input string: abcd\nefgh\nijkl\nmnop
#!/bin/bash
oper () {
local fct=$1
local s=$2
IFS='\n' read -ra sArr <<< "$s"
for item in ${sArr[#]}
do
printf " %s\n" $(echo $item | rev)
done
}
echo "original string: $2"
oper $1 $2
printf "mirror string: "
exit 0
Here's the output
original string: abcd\nefgh\nijkl\nmnop
dcba
hgfe
lkji
m
po
Why are the last two array elements being truncated?
Because any character in IFS causes splitting into words, not both. Seeting IFS='\n' splits the input string on \ or n. Because mnop has an n in it, it is splitted to m and op.
First change the sequence of \n character to something that is a single character and uniq - then you may use IFS=.. read. For example:
IFS='!' read -r -a sarr < <(sed 's/\\n/!/g' <<<"$s")
Remember to check you script with http://shellcheck.net to correct quoting problems.

Saving part of each line to an array in bash

I am trying to read from a file that is storing user names and addresses in the format of name:address on each new line and I wish to store only the addresses into an array. Is there any way to do this? My code currently looks like this:
while IFS=: read -r username address; do
array=${address}
done <userfile.txt
Which is only storing the address from the first line in the file and stopping.
You are almost right! You just need to append to the array using the += operator (append) which bash arrays provide.
declare -a myArray=()
while IFS=: read -r username address; do
myArray+=("$address")
done < userfile.txt
Doing the above should do the trick for you. Note that the parentheses are also critical here. array+=(something) appends a new element to the array, while array+=something just appends text to the first element of the array. Optionally later to print the array contents each in separate line use printf as
printf "%s\n" "${myArray[#]}"
You can use array+=($address) form of adding array element.
array=()
while IFS=: read -r username address; do
array+=("$address")
done < userfile.txt
echo ${array[#]}

Read array from file separated with commas and newlines

I have a file that has two different words per line, delimited by a comma and a line break. How can you read this file and store every word in an array? My code doesn't work because I think only works for "one line" array.
File Sample:
Each word is separated by a comma and a line break.
Dog,cat
shark,rabbit
mouse,bird
whale,dolphin
Desired input
"${array[0]}" = Dog
"${array[1]}" = cat
"${array[2]}" = shark
"${array[3]}" = rabbit
"${array[4]}" = mouse
"${array[5]}" = bird
"${array[6]}" = whale
"${array[7]}" = dolphin
My Code:
input=$(cat "/path/source_file")
IFS=',' read -r -a array <<< "$input"
IFS=$'\n,' read -d '' -ra array < file
The key is to use IFS to tell read to split the entire input) -d '') into array elements (-a; -r ensures unmodified reading) by both \n and , characters.
For simplicity, I've used file to represent your input file and used it directly as input to read via stdin (<).
If you do have a need to read the entire file into a shell variable first, the following form is slightly more efficient in Bash (but is not POSIX-compliant):
input=$(< "/path/source_file")
Input Format:
Read the inarr1 from line 1 with array elements separated by (,) comma.
Read the inarr2 from line 2 with array elements separated by (,) comma.
Read the input from the standard input stream
Output format:

Bash: replace text in nth line of file with nth index of array

Trying to replace MAC Addresses in a flat file. In the code below, the addresses are successfully mapping to the array. I've tried to use a counter to increment the array index on each loop, with the intent of replacing the address on line n with the nth address in the array.
The sed block effectively replaces the addresses, but only with the entry at array index 0.
mapfile -t Arr1 < <(text processing commands)
i=0
while read line
do
sed -E "s/([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}/${Arr1[$i]}/"
((i++))
done < $macFile
The problem is that sed is reading from standard input, so instead of reading the contents of the $line variable, it's reading the contents of the file designated by $macFile (except the first line, which has already been grabbed by read).
To fix this, add <<< "$line" to the end of your sed command.

How to read and split comma separated file in a bash shell script?

I want to read a file line by line, split each line by comma (,) and store the result in an array. How to do this in a bash shell script?
Sample line in my comma separated file
123,2014-07-21 10:01:44,123|8119|769.00||456|S
This should be the output after splitting:
arr[0]=123 arr[1]=2014-07-21 10:01:44 arr[2]=123|8119|769.00||456|S
Use read -a to split each line read into array based from IFS.
while IFS=, read -ra arr; do
## Do something with ${arr0]}, ${arr[1]} and ${arr[2]}
...
done < file
If the third field can also contain commas, you can prevent it from being split by using finite non-array parameters:
while IFS=, read -r a b c; do
## Do something with $a, $b and $c
...
done < file
From help read:
Reads a single line from the standard input, or from file descriptor FD
if the -u option is supplied. The line is split into fields as with word
splitting, and the first word is assigned to the first NAME, the second
word to the second NAME, and so on, with any leftover words assigned to
the last NAME. Only the characters found in $IFS are recognized as word
delimiters.
-a array assign the words read to sequential indices of the array
variable ARRAY, starting at zero

Resources