另一个数组定义中的数组值重用

时间:2018-11-26 18:31:58

标签: arrays bash dynamic-arrays

我正在尝试使用另一个数组的值作为新数组的名称在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

例如,从Header2列中获取值2。 目的是动态创建具有值Value1和Value2的数组2:

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 :(得分:0)

最后,我根据要简化的注释选择了一种更简单的方法:

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文件。

我真的很想以最初的方式完成此操作,因为它更适合于更多数据...

答案 1 :(得分:0)

如果我没看错,并且假设您明确地将它们压出后,您可以在文件上没有适当的换行符,那么应该在一次awk调用中完成以上所有操作。

awk -F'[; ]' '/;[0-9] / { for (i=2; i<=NF; i++) printf "%s ", $1 > $i".txt" }' yourInputFile

答案 2 :(得分:0)

使用数组全扑灭-

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链。

还需要更多吗?