Повторное использование значений массива в другом определении массива - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь выполнить определение массива в bash, используя значения другого массива в качестве имени нового массива и назначить значения внутри массива из другого массива, который динамически заполняется.

Вот пример кода на данный момент:

adduser() {
  declare -i segment=$1
  segment_length=${#segment[@]}
  for (( a = 0; a < "${segment_length}"; a++ )); do
    data=($(cat $filename | grep -w ${segment[a]} | awk -F ";" '{print $1}' | tr '\n' ' ' | sed 's/^/ /g'))
    ${segment[a]}=($(echo "${data[*]}"))
  done
}

cat $filename | tail -n+2 | awk -F ";" '{print $2}' | awk '{ for (i=1; i<=NF; i++) print $i }' | sed 's/\r//g' | sort -u > segments.txt
IFS=$'\r\n' GLOBIGNORE='*' command eval  'segments=($(cat segments.txt))'
for (( i = 0; i < ${#segments[@]}; i++ )); do
adduser ${segments[i]}
done

Цель состоит в том, чтобы динамически заполнять массивы (данные в одном столбце csv) значениями из другого столбца, а затем массово работать надих.

CSV имеет следующий формат:

Header1;Header2
Value1;1 2 3
Value2;2 4 5

Возьмем, например, значение 2 из столбца Header2.Задача состоит в том, чтобы динамически создать массив 2 со значениями Value1 и Value2:

2=( Value1 Value2 )

Проверка предоставленных двух ответов:

Я продолжу здесь, поскольку комментарии слишкомкратко: Вот результат ответа со случайным файлом (в том же формате, что и в примере):

ivo@spain-nuc-03:~/Downloads/TestStackoverflow$ awk -F'[; ]' '/;[0-9] / { for (i=2; i<=NF; i++) printf "%s ", $1 > $i".txt" }' real.csv 
ivo@spain-nuc-03:~/Downloads/TestStackoverflow$ ll
total 68
drwxr-xr-x  2 ivo ivo  4096 Nov 27 17:16 ./
drwxr-xr-x 28 ivo ivo 32768 Nov 27 17:15 ../
-rw-rw-r--  1 ivo ivo    99 Nov 27 17:16 155.txt
-rw-rw-r--  1 ivo ivo   132 Nov 27 17:16 155?.txt
-rw-rw-r--  1 ivo ivo    99 Nov 27 17:16 2.txt
-rw-rw-r--  1 ivo ivo    66 Nov 27 17:16 2?.txt
-rw-rw-r--  1 ivo ivo   198 Nov 27 17:16 3.txt
-rw-rw-r--  1 ivo ivo    33 Nov 27 17:16 3?.txt
-rw-r--r--  1 ivo ivo  1369 Nov 27 17:14 real.csv

В то время как с ответом выше вы получите следующее:

ivo@spain-nuc-03:~/Downloads/TestStackoverflow$ ./processing.sh real.csv

ivo@spain-nuc-03:~/Downloads/TestStackoverflow$ ll
total 112
drwxr-xr-x  2 ivo ivo  4096 Nov 27 17:25 ./
drwxr-xr-x 28 ivo ivo 32768 Nov 27 17:15 ../
-rw-rw-r--  1 ivo ivo   100 Nov 27 17:25 102.txt
-rw-rw-r--  1 ivo ivo   100 Nov 27 17:25 105.txt
-rw-rw-r--  1 ivo ivo    67 Nov 27 17:25 106.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 112.txt
-rw-rw-r--  1 ivo ivo   991 Nov 27 17:25 155.txt
-rw-rw-r--  1 ivo ivo   694 Nov 27 17:25 2.txt
-rw-rw-r--  1 ivo ivo   859 Nov 27 17:25 3.txt
-rw-rw-r--  1 ivo ivo    67 Nov 27 17:25 51.txt
-rw-rw-r--  1 ivo ivo    67 Nov 27 17:25 58.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 59.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 65.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 67.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 72.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 78.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 81.txt
-rw-rw-r--  1 ivo ivo    34 Nov 27 17:25 82.txt
-rwxrwxr-x  1 ivo ivo  1180 Nov 27 17:25 processing.sh*
-rw-r--r--  1 ivo ivo  1369 Nov 27 17:14 real.csv
ivo@spain-nuc-03:~/Downloads/TestStackoverflow$

Спасибовсем за участие!

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Если я правильно читаю и предполагаю, что у вас все в порядке с отсутствием надлежащего перевода строки в файлах, поскольку вы явно уничтожили их, это должно сделать все вышеописанное в одном вызове awk.

awk -F'[; ]' '/;[0-9] / { for (i=2; i<=NF; i++) printf "%s ", $1 > $i".txt" }' yourInputFile
0 голосов
/ 27 ноября 2018

All-bash с использованием массива -

declare -a set=()                          # set is an array
while IFS=';' read -r key lst              # read each line into these 2 splitting on semicolons
do [[ $key =~ Header* ]] && continue       # ignore the header
   read -a val <<< "$lst"                  # split the list of values to the right of the semicolon into an array
   for e in "${val[@]}"                    # for each of those
   do  case "${set[e]:-}" in               
       *$key*) : already here, no-op   ;;  # ignore if already present
           '') set[e]="$key"           ;;  # set initial if empty
            *) set[e]="${set[e]} $key" ;;  # add delimited if new
       esac
   done
done < csv                                 # reads directly from the CSV file

На этом этапе наборы должны быть загружены в виде строк, разделенных пробелами, в каждый элемент set[], проиндексированных значениями в строке во втором столбцеиз csv.Чтобы распечатать их для проверки -

for n in "${!set[@]}"
do echo "$n: ${set[n]}"
done

Выполняется при проверке содержимого CSV:

1: Value1
2: Value1 Value2
3: Value1
4: Value2
5: Value2

, поэтому set[4] равно Value2, а set[2] равно Value1 Value2,Вы можете вытащить их оттуда, чтобы сделать все необходимое.

Нет необходимости в цепях cat / tail / awk / grep / tr / sed / sort.

Нужно ли что-то еще?

0 голосов
/ 27 ноября 2018

Наконец я пошел по более простому методу в соответствии с комментариями, которые я получил, чтобы упростить:

cat $1 | tail -n+2 | awk -F ";" '{print $2}' | awk '{ for (i=1; i<=NF; i++) print $i }' | sed 's/\r//g' | sort -u > segments.txt
IFS=$'\r\n' GLOBIGNORE='*' command eval  'segments=($(cat segments.txt))'
for (( i = 0; i < ${#segments[@]}; i++ )); do
cat $1 | grep -w ${segments[i]} | awk -F ";" '{print $1}' | tr '\n' ' ' | sed 's/^/ /g' > ${segments[i]}.txt
done
rm segments.txt

А затем просто обработать оставшиеся txt-файлы в папке.

Мне бы очень хотелось, чтобы это было сделано так, как я делал изначально, хотя это больше подходит для большего количества данных ...

...