BASH-перемешивание символов в строках из файла
У меня есть файл (filename.txt) со следующей структурой:
>line1
ABC
>line2
DEF
>line3
GHI
>line4
JKL
Я хотел бы перетасовать символы в строках, которые делают не start wit >. Выходные данные (например) будут выглядеть следующим образом:
>line1
BCA
>line2
DFE
>line3
IHG
>line4
KLJ
Это то, что я пытался перетасовать символы в строке: sed 's/./&n/' | shuf | tr -d "n". Похоже, что это работает, но не учитывает новые строки. Более того, он выполняет команду на всех данных, а не только на строках, которые не начинаются с >.
5 ответов:
С
perlиruby$ # split// to get individual characters $ # join "" to join characters with empty string $ # if !/^>/ to apply the change only for lines not starting with > $ # alternate: perl -MList::Util=shuffle -lne 'print /^>/ ? $_ : shuffle split//' $ perl -MList::Util=shuffle -lpe '$_=join "", shuffle split// if !/^>/' ip.txt >line1 CBA >line2 FED >line3 IHG >line4 JKL $ # $_.chars to get individual characters $ # * "" to join array elements with empty string $ ruby -lpe '$_ = $_.chars.shuffle * "" if !/^>/' ip.txt >line1 BAC >line2 EDF >line3 GHI >line4 JKL
awk+coreutilsподход:awk '/^[^>]/{ system("echo "$1"| fold -w1 | shuf | tr -d \047\n\047"); print ""; next }1' fileПример вывода:
>line1 BAC >line2 EDF >line3 HGI >line4 KLJ
Для
GNU sed:$ cat filename.txt >line1 ABC >line2 DEF >line3 GHI >line4 JKL $ sed -r "/^[^>]/s/.*/grep -o . <<< & |sort -R |tr -d '\n'/e" filename.txt >line1 ABC >line2 FDE >line3 HGI >line4 LKJ $ sed -r "/^[^>]/s/.*/grep -o . <<< & |shuf |tr -d '\n'/e" filename.txt >line1 BCA >line2 FDE >line3 HIG >line4 JKLEdit:
sedработает все так же на всех(GNU sed) 4.2.2, мы можем распечатать сырую командную строку, сгенерированную sed, удалив модификаторe:sed -r '/^[^>]/s/.*/grep -o . <<< & |shuf |tr -d "\n"/' filename.txt >line1 grep -o . <<< ABC |shuf |tr -d " " >line2 grep -o . <<< DEF |shuf |tr -d " " >line3 grep -o . <<< GHI |shuf |tr -d " " >line4 grep -o . <<< JKL |shuf |tr -d " "Тогда модификатор
eкомандыssedвызоветshдля ее выполнения.shнаCentOSявляется символической ссылкой наbash, но на Ubuntu это символическая ссылка наdash, иdash, возможно, не поддерживает<<<(here-string).# on Ubuntu, enter into sh terminal: $ grep -o . <<< JKL |shuf |tr -d '\n' sh: 2: Syntax error: redirection unexpected $ echo JKL |grep -o . |shuf |tr -d '\n' KLJИтак, мне нужно изменить свой ответ, чтобы он работал для обоих
bashиdash:$ sed -r '/^[^>]/s/.*/echo -n & |grep -o . |shuf |tr -d "\n"/e' filename.txt >line1 ACB >line2 DFE >line3 IHG >line4 LJKПростые объяснения:
/^[^>]/: заставитьsedиметь дело с линиями, которые начинаются (^) не с a>([^>]).- Наконец, используйте модификатор
s/.*/echo -n & |grep -o . |shuf |tr -d "\n"/:.*это вся строка, используйте&, чтобы держать ее в замене, так что&- это вся исходная строка, а затем создайте простую командную строкуecho -n ORIGIN_LINE |grep -o . |shuf |tr -d "\n", которая может перетасовать строку.eкомандыsдля выполнения простой командной строки, сгенерированной выше.
Вот один в GNU awk:
$ awk -v seed=$RANDOM ' # get some randomness from shell function cmp_randomize(i1, v1, i2, v2) { # random for traversal function return (2 - 4 * rand()) # from 12.2.1 Controlling Array Traversal } # of Gnu awk docs BEGIN { srand(seed) # use the seed, Luke PROCINFO["sorted_in"]="cmp_randomize" # use above defined function } /^[^>]/ { # if starts with anything but > split($0,a,"") # split to hash a for(i in a) # iterate a in random order printf "%s", a[i] # output print "" # newline next # next record }1' file # output > starting records >line1 CAB >line2 DFE >line3 GIH >line4 LKJ
Это может сработать для вас (GNU sed):
sed '/^>/b;s/./&\n/g;s/.$//;s/.*/echo "&"|shuf/e' fileВыводите строки, начинающиеся с
>, но не обрабатывайте их. В противном случае вставьте новые строки между каждым символом в текущей строке и удалите последнюю нежелательную новую строку. Затемechoсозданный файл и передать его через командуshuf(sort-R может быть заменен при необходимости) и распечатать результат.N. B. Это решение использует флаг GNU specific
eв команде подстановки, однако результат может быть передан в оболочку, например Итак:sed '/^>/s/.*/echo "&"/;t;s/./&\n/g;s/.$//;s/.*/echo "&"|shuf/' file | sh
Comments