명령 출력에서 ​​공백이 있는 요소로 배열을 초기화하는 방법

명령 출력에서 ​​공백이 있는 요소로 배열을 초기화하는 방법

다음 스크립트:

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

다음 샘플 .log 파일을 사용하십시오.

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

다음과 같은 원치 않는 출력이 생성됩니다.

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

원하는 출력에는 18개가 아닌 9개의 요소만 포함되어야 하며, 각 요소에는 원시 공백으로 구분된 날짜와 시간이 포함됩니다.

어레이 초기화를 유지하면서 스크립트를 수정하려면 어떻게 해야 합니까?단 9개 요소, 이것을 달성하려면?

답변1

mapfile -t다음과 같이 프로세스 대체에서 데이터를 사용하고 읽을 수 있습니다.@쿠살라난다지적했다.

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

또는 IFS단어 분리에 사용되는 변수를 개행 문자(기본값은 공백, 탭 및 개행 문자)로 변경한 다음 다시 원래 값으로 변경할 수 있습니다.

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

출력(두 가지 변형):

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

관련된:

답변2

awk '{print NR-1 ": ", "start:", $1, $2;}' sample.log

질문에 인쇄된 입력을 사용하세요.

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

출력 형식을 더 효과적으로 제어하려면 다음을 printf사용할 수도 있습니다.

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

명령 대체에는 공백이나 특수 문자가 있는 경우 몇 가지 단점이 있습니다. 분명히 입력의 두 필드는 별도의 배열 요소에 보관됩니다. 이 스크립트는 원본 스크립트를 기반으로 이를 결합합니다.

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

관련 정보