BASH - 来自文件的字符串中的随机字符

时间:2018-03-29 12:20:32

标签: bash awk sed shuffle lines

我有一个文件(filename.txt),结构如下:

>line1
ABC
>line2
DEF
>line3
GHI
>line4
JKL

我想将启动机智>的字符串中的字符洗牌。输出(例如)如下所示:

>line1
BCA
>line2
DFE
>line3
IHG
>line4
KLJ

这就是我试图将字符串中的字符混洗:sed 's/./&\n/' | shuf | tr -d "\n"。看起来它有效,但它没有考虑换行。此外,它对所有数据执行命令,而不仅对不以>开头的行执行命令。

5 个答案:

答案 0 :(得分:3)

使用perlruby

$ # 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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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
JKL

编辑:sed在所有(GNU sed) 4.2.2上都运行相同,我们可以通过删除e修饰符来打印由sed生成的原始命令字符串:

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的{​​{1}}命令的s修饰符将调用sed来执行它。 sh上的sh是指向CentOS的符号链接,但在Ubuntu上,它是指向bash的符号链接,而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

简单解释:

  1. $ sed -r '/^[^>]/s/.*/echo -n & |grep -o . |shuf |tr -d "\n"/e' filename.txt >line1 ACB >line2 DFE >line3 IHG >line4 LJK :强制/^[^>]/处理以sed^)开头的行(>)。
  2. [^>]s/.*/echo -n & |grep -o . |shuf |tr -d "\n"/是整行,使用.*来替换它,因此&是整个原始行,然后生成一个普通的命令字符串{ {1}},可以改变界限。
  3. 最后,使用&命令的echo -n ORIGIN_LINE |grep -o . |shuf |tr -d "\n"修饰符来执行上面生成的普通命令字符串。

答案 3 :(得分:1)

这是GNU awk中的一个:

basicSalary

答案 4 :(得分:0)

这可能适合你(GNU sed):

sed '/^>/b;s/./&\n/g;s/.$//;s/.*/echo "&"|shuf/e' file

打印以>开头但不处理的行。否则,在当前行中的每个字符之间插入换行符,并删除最后一个不需要的换行符。然后echo生成文件并通过shuf命令管道(如果需要,可以替换排序-R)并打印结果。

N.B。此解决方案在替换命令上使用GNU特定的e标志,但结果可以传递给shell,如下所示:

sed '/^>/s/.*/echo "&"/;t;s/./&\n/g;s/.$//;s/.*/echo "&"|shuf/' file | sh