0

The following script:

DYN_HOSTS_START_ARRAY=($(grep -E "STARTING HOST" sample.log | cut -d' ' -f 1,2))
for ((i=0; i< ${#DYN_HOSTS_START_ARRAY[@]}; i++))
do
    echo "$i:  start: "${DYN_HOSTS_START_ARRAY[$i]}""
done

Using the following sample.log file:

2019-11-11 19:05:55,823 DEBUG  STARTING HOST 46
2019-11-11 19:05:55,831 DEBUG  STARTING HOST 703
2019-11-11 19:05:55,837 DEBUG  STARTING HOST 505
2019-11-11 19:05:55,858 DEBUG  STARTING HOST 93
2019-11-11 19:05:55,859 DEBUG  STARTING HOST 486
2019-11-11 19:05:55,861 DEBUG  STARTING HOST 72
2019-11-11 19:05:55,879 DEBUG STARTING HOST 855
2019-11-11 19:05:55,913 DEBUG  STARTING HOST 560
2019-11-11 19:05:56,067 DEBUG STARTING HOST 199

Yields the following undesired output:

0:  start: 2019-11-11
1:  start: 19:05:55,823
2:  start: 2019-11-11
3:  start: 19:05:55,831
4:  start: 2019-11-11
5:  start: 19:05:55,837
6:  start: 2019-11-11
7:  start: 19:05:55,858
8:  start: 2019-11-11
9:  start: 19:05:55,859
10:  start: 2019-11-11
11:  start: 19:05:55,861
12:  start: 2019-11-11
13:  start: 19:05:55,879
14:  start: 2019-11-11
15:  start: 19:05:55,913
16:  start: 2019-11-11
17:  start: 19:05:56,067

The desired output should only have 9 elements (instead of 18), each element containing both the date and the time, separated by the original space.

How do I fix my script, while retaining the array initialization, to 9 elements only, to accomplish that?

2 Answers 2

1

You could use mapfile -t and read the your data from a process substitution as @Kusalananda pointed out.

mapfile -t dyn_hosts_start_array < <(grep 'STARTING HOST' sample.log | cut -d' ' -f 1,2)    
for i in "${!dyn_hosts_start_array[@]}"; do
  printf '%s:  start: %s\n' "$i" "${dyn_hosts_start_array[i]}"
done

Or you could change the IFS variable which is used for word splitting to a newline character (default value is space character, tab and newline) and change it back to its original value afterwards.

oldifs=$IFS
IFS=$'\n'
dyn_hosts_start_array=( $(grep 'STARTING HOST' sample.log | cut -d' ' -f 1,2) )
IFS=$oldifs    
for i in "${!dyn_hosts_start_array[@]}"; do
  printf '%s:  start: %s\n' "$i" "${dyn_hosts_start_array[i]}"
done

Output (both variants):

0:  start: 2019-11-11 19:05:55,823
1:  start: 2019-11-11 19:05:55,831
2:  start: 2019-11-11 19:05:55,837
3:  start: 2019-11-11 19:05:55,858
4:  start: 2019-11-11 19:05:55,859
5:  start: 2019-11-11 19:05:55,861
6:  start: 2019-11-11 19:05:55,879
7:  start: 2019-11-11 19:05:55,913
8:  start: 2019-11-11 19:05:56,067

Related:

2
  • Or use mapfile -t from a process substitution.
    – Kusalananda
    Commented Dec 18, 2019 at 18:46
  • @Kusalananda Indeed, that's much better. Thank you.
    – Freddy
    Commented Dec 18, 2019 at 19:09
1
awk '{print NR-1 ": ", "start:", $1, $2;}' sample.log

with the input from the question prints

0:  start: 2019-11-11 19:05:55,823
1:  start: 2019-11-11 19:05:55,831
2:  start: 2019-11-11 19:05:55,837
3:  start: 2019-11-11 19:05:55,858
4:  start: 2019-11-11 19:05:55,859
5:  start: 2019-11-11 19:05:55,861
6:  start: 2019-11-11 19:05:55,879
7:  start: 2019-11-11 19:05:55,913
8:  start: 2019-11-11 19:05:56,067

To have more control over the output formatting you could also use printf like this

awk '{printf "%d:  start: %s %s\n", NR-1, $1, $2;}' sample.log

Command substitution has some pitfalls with whitespace or special characters. Apparently, the two fields from the input are saved in separate array elements. This script combines them based on your original script.

DYN_HOSTS_START_ARRAY=($(grep -E "STARTING HOST" sample.log | cut -d' ' -f 1,2))
for ((i=0; i< ((${#DYN_HOSTS_START_ARRAY[@]} / 2)); i++))
do
    echo "$i:  start: ${DYN_HOSTS_START_ARRAY[((2 * $i))]} ${DYN_HOSTS_START_ARRAY[((2 * $i + 1))]}"
done
5
  • Thank you but that does not initialize any array... ?
    – datsb
    Commented Dec 18, 2019 at 17:50
  • 1
    @datsb You did not tell in the question that the contents of the array is important, you only complained about the wrong output. So edit your question (using the edit link below the question) and state what you want to achieve.
    – Bodo
    Commented Dec 18, 2019 at 17:54
  • Thank you. That works. Is there a way to prevent the number of elements in the array from doubling?
    – datsb
    Commented Dec 18, 2019 at 18:05
  • Instead of adding questions in comments, write everything to your question with enough details to allow us to understand what is important for you. If you care about the contents of the array, tell in your question how the array elements should look like.
    – Bodo
    Commented Dec 18, 2019 at 18:10
  • Original question re-edited to clarify the 2 requirements. The subject line also clarifies that.
    – datsb
    Commented Dec 18, 2019 at 18:12

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.