2023-01-25 19:24:47 +00:00
|
|
|
---
|
|
|
|
tags:
|
|
|
|
- shell
|
|
|
|
---
|
|
|
|
|
|
|
|
# Splitting input into an array
|
|
|
|
|
2023-02-26 11:56:30 +00:00
|
|
|
## readarray
|
2023-01-25 19:24:47 +00:00
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
`readarray` makes it really easy to split input into an array based on new
|
|
|
|
lines. Say we have this file as input:
|
2023-01-25 19:24:47 +00:00
|
|
|
|
|
|
|
```
|
|
|
|
123
|
|
|
|
456
|
|
|
|
789
|
|
|
|
```
|
|
|
|
|
|
|
|
Then we can split like so:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
readarray -t name_for_array < ./input.text
|
|
|
|
|
|
|
|
# Print all elements
|
|
|
|
echo "${name_for_array[@]}"
|
|
|
|
|
|
|
|
# Print element by index
|
|
|
|
|
|
|
|
echo "${name_for_array[1]}"
|
|
|
|
456
|
|
|
|
```
|
|
|
|
|
2023-03-08 07:11:40 +00:00
|
|
|
If we want to read a string directly:
|
2023-01-25 19:24:47 +00:00
|
|
|
|
|
|
|
```bash
|
|
|
|
readarray -t new_name_for_array <<< "here
|
|
|
|
is
|
|
|
|
some
|
|
|
|
text"
|
|
|
|
|
|
|
|
echo "${new_name_for_array[1]}"
|
|
|
|
is
|
|
|
|
```
|
|
|
|
|
|
|
|
> The _-t_ flag removes the trailing newline
|
|
|
|
|
2023-03-08 07:11:40 +00:00
|
|
|
See more: https://linuxhint.com/split-string-array-bash/
|
2023-02-04 09:26:34 +00:00
|
|
|
|
2023-02-26 11:56:30 +00:00
|
|
|
## read
|
2023-02-04 09:26:34 +00:00
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
For delimiters other than a space we have to use `read`, combined with `IFS` the
|
|
|
|
**Internal Field Separator**.
|
2023-02-04 09:26:34 +00:00
|
|
|
|
|
|
|
For example, to split by comma:
|
|
|
|
|
|
|
|
```plaintext
|
|
|
|
# comma-input.txt
|
2023-03-08 07:11:40 +00:00
|
|
|
something,something else,something more
|
2023-02-04 09:26:34 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
```bash
|
|
|
|
IFS=',' read -a arr < ./comma_inputs.txt
|
|
|
|
```
|
2023-02-26 11:56:30 +00:00
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
> We use the `-a` flag to signal that we want each item read returned as an
|
|
|
|
> element in an array
|
2023-02-26 11:56:30 +00:00
|
|
|
|
|
|
|
## mapfile
|
|
|
|
|
|
|
|
We can use `mapfile` to read the lines of a input file in set segments.
|
|
|
|
|
|
|
|
For the following file:
|
|
|
|
|
|
|
|
```
|
|
|
|
line one
|
|
|
|
line two
|
|
|
|
line three
|
|
|
|
line four
|
|
|
|
```
|
|
|
|
|
|
|
|
We could generate the following output:
|
|
|
|
|
|
|
|
```
|
|
|
|
-----SNIP-----
|
|
|
|
line one
|
|
|
|
line two
|
|
|
|
-----SNIP-----
|
|
|
|
line three
|
|
|
|
line four
|
|
|
|
```
|
|
|
|
|
|
|
|
With:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
while mapfile -t -n 2 ary && ((${#ary[@]})); do
|
|
|
|
printf '%s\n' "${ary[@]}"
|
|
|
|
printf -- '--- SNIP ---\n'
|
|
|
|
done < $testInput
|
|
|
|
```
|
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
So, while there are input lines, map each line into an array and return it in
|
|
|
|
groups of 2.
|