BASH разделил одну строку на пару ключ-значение. Например, A,B,C | 1,2,3 к A,1 B,2 C,3

#bash #split #zsh #pcap #tshark

Вопрос:

Я использую Tshark, чтобы разделить некоторые данные. Проблема в том, что данные отображаются в одной строке. Чтобы использовать его, я хотел бы разделить его на пары ключ-значение. Например:

Данные Tshark- a,b,c,d,e,f,g | 1,2,3,4,5,6,7

Хотел бы отформатировать так — a,1 b,2 c,3 d,4 e,5 f,6 g,7

или — [{a,1},{b,2}] etc..

Спасибо!

Комментарии:

1. bash или zsh ?

2. Сделайте это в несколько этапов. Сначала разделите всю строку | на две переменные. Затем разделите каждую из этих переменных на массивы , . Затем выполните цикл по индексам массива, объединяя соответствующие элементы каждого массива.

3. Если это вопрос bash, то почему у вас в тегах есть zsh? Это две разные оболочки, и они не совместимы друг с другом.

4. может помочь узнать, как вы планируете использовать эти данные и, следовательно, соответствующий способ сохранения/хранения переформатированных данных (например, (ассоциативный) массив)? пары с пробелами в одной строке? структура yaml/json/xml?)

Ответ №1:

 #!/usr/bin/env bash
#              ^^^^ - note bash; not zsh, not sh

processLine() {
  local data idx      # declare locals so we don't pollute global namespace
  local -a arr1 arr2  # declare local arrays separately
  data=$1             # assign our first positional argument to $data

  # no separator? bail out early
  [[ $data = *" | "* ]] || {
    echo "ERROR: Data not in expected form" >amp;2
    return 1
  }

  # break our two variables into two separate arrays
  IFS=, read -r -a arr1 <<<"${data%%' | '*}"
  IFS=, read -r -a arr2 <<<"${data#*' | '}"

  # iterate over those arrays by index/key to pair items up
  for idx in "${!arr1[@]}"; do
    printf '%s,%s ' "${arr1[$idx]}" "${arr2[$idx]}"
  done
  printf 'n'  # add a trailing newline
}

processLine 'a,b,c,d,e,f,g | 1,2,3,4,5,6,7'
 

Смотрите, как это работает на https://ideone.com/6Ugk0H

Ответ №2:

Попробуйте это awk

 $ echo "a,b,c,d,e,f,g | 1,2,3,4,5,6,7" | awk -F"[|, ] " ' { for(i=1;i<=NF/2;i  ) printf $i "," $(i NF/2) " " } '
a,1 b,2 c,3 d,4 e,5 f,6 g,7
 

Ответ №3:

Поскольку вы zsh также отметили это, zsh решение, использующее только расширение параметров:

 #!/usr/bin/env zsh

data="a,b,c,d,e,f,g | 1,2,3,4,5,6,7"

# Split on pipe into an array
halves=( ${(s:|:)data} ) 
# Split the first array element on comma, first removing trailing spaces
first=( ${(s:,:)${halves[1]%% }} )
# Same with the second element and leading spaces
second=( ${(s:,:)${halves[2]## }} )

# Merge the two arrays by alternating elements, and print out two elements
# at a time so it looks like
# a,1 b,2 c,3 d,4 e,5 f,6 g,7
printf "%s,%s " ${first:^second}
printf "n"

# Or to render as
# [{a,1},{b,2},{c,3},{d,4},{e,5},{f,6},{g,7}]
pairs=$(printf "{%s,%s}01" ${first:^second})
printf "[%s]n" "${(j:,:)${(ps:01:)pairs}}"