Простой способ перемешать элементы массива в оболочке BASH? - PullRequest
9 голосов
/ 04 апреля 2011

Я могу сделать это на PHP, но я пытаюсь работать в оболочке BASH. Мне нужно взять массив, а затем случайным образом перемешать содержимое и вывести его на somefile.txt.

Таким образом, для данного массива Heresmyarray, из элементов a;b;c;d;e;f; будет получен выходной файл output.txt, который будет содержать элементы f;c;b;a;e;d;

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

Ответы [ 3 ]

14 голосов
/ 13 февраля 2017

Принятый ответ не соответствует заголовку вопроса слишком хорошо, хотя детали в вопросе немного неоднозначны. Вопрос состоит в том, как перетасовать элементы массива в BASH, и ответ Куруми показывает способ манипулирования содержимым строки.

kurumi, тем не менее, хорошо использует команду 'shuf', а siegeX показывает, как работать с массивом.

Соединение двух вместе дает реальный «простой метод перемешивания элементов массива в оболочке BASH»:

$ myarray=( 'a;' 'b;' 'c;' 'd;' 'e;' 'f;' )
$ myarray=( $(shuf -e "${myarray[@]}") )
$ printf "%s" "${myarray[@]}"
d;b;e;a;c;f;
9 голосов
/ 04 апреля 2011

От BashFaq

Эта функция перемешивает элементы массива на месте, используя алгоритм перемешивания Кнута-Фишера-Йейтса.

#!/bin/bash

shuffle() {
   local i tmp size max rand

   # $RANDOM % (i+1) is biased because of the limited range of $RANDOM
   # Compensate by using a range which is a multiple of the array size.
   size=${#array[*]}
   max=$(( 32768 / size * size ))

   for ((i=size-1; i>0; i--)); do
      while (( (rand=$RANDOM) >= max )); do :; done
      rand=$(( rand % (i+1) ))
      tmp=${array[i]} array[i]=${array[rand]} array[rand]=$tmp
   done
}

# Define the array named 'array'
array=( 'a;' 'b;' 'c;' 'd;' 'e;' 'f;' )

shuffle
printf "%s" "${array[@]}"

Выход

$ ./shuff_ar > somefile.txt
$ cat somefile.txt
b;c;e;f;d;a;
8 голосов
/ 04 апреля 2011

Если вы просто хотите поместить их в файл (используйте перенаправление>)

$ echo "a;b;c;d;e;f;" | sed -r 's/(.[^;]*;)/ \1 /g' | tr " " "\n" | shuf | tr -d "\n"
  d;a;e;f;b;c;

$ echo "a;b;c;d;e;f;" | sed -r 's/(.[^;]*;)/ \1 /g' | tr " " "\n" | shuf | tr -d "\n" > output.txt

Если вы хотите поместить элементы в массив

$ array=( $(echo "a;b;c;d;e;f;" | sed -r 's/(.[^;]*;)/ \1 /g' | tr " " "\n" | shuf | tr -d " " ) )
$ echo ${array[0]}
e;
$ echo ${array[1]}
d;
$ echo ${array[2]}
a;

Если ваши данные имеют &#abcde;

$ echo "a;&#abcde;c;d;e;f;" | sed -r 's/(.[^;]*;)/ \1 /g' | tr " " "\n" | shuf | tr -d "\n"
d;c;f;&#abcde;e;a;
$ echo "a;&#abcde;c;d;e;f;" | sed -r 's/(.[^;]*;)/ \1 /g' | tr " " "\n" | shuf | tr -d "\n"
&#abcde;f;a;c;d;e;
...