使用 bash 生成排列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3846123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:43:07  来源:igfitidea点击:

Generating permutations using bash

bashshellpermutation

提问by siliconpi

is it possible to write a bash script that can read in each line from a file and generate permutations (without repetition) for each? Using awk / perl is fine.

是否可以编写一个 bash 脚本,该脚本可以从文件中读取每一行并为每一行生成排列(不重复)?使用 awk / perl 很好。

File
----
ab
abc


Output
------
ab
ba
abc
acb
bac
bca
cab
cba

回答by jlonganecker

I know I am a little late to the game but why not brace expansion?

我知道我玩游戏有点晚了,但为什么不扩展支架呢?

For example:

例如:

echo {a..z}{0..9}

Outputs:

输出:

a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 j0 j1 j2 j3 j4 j5 j6 j7 j8 j9 k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 l0 l1 l2 l3 l4 l5 l6 l7 l8 l9 m0 m1 m2 m3 m4 m5 m6 m7 m8 m9 n0 n1 n2 n3 n4 n5 n6 n7 n8 n9 o0 o1 o2 o3 o4 o5 o6 o7 o8 o9 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 y0 y1 y2 y3 y4 y5 y6 y7 y8 y9 z0 z1 z2 z3 z4 z5 z6 z7 z8 z9

Another useful example:

另一个有用的例子:

for X in {a..z}{a..z}{0..9}{0..9}{0..9}
    do echo $X;
done

回答by livibetter

Pure bash (using local, faster, but can't beat the other answer using awk below, or the Python below):

纯 bash(使用local,更快,但无法使用下面的 awk 或下面的 Python 击败其他答案):

perm() {
  local items=""
  local out=""
  local i
  [[ "$items" == "" ]] && echo "$out" && return
  for (( i=0; i<${#items}; i++ )) ; do
    perm "${items:0:i}${items:i+1}" "$out${items:i:1}"
  done
  }
while read line ; do perm $line ; done < File

Pure bash (using subshell, much slower):

纯 bash(使用子shell,慢得多):

perm() {
  items=""
  out=""
  [[ "$items" == "" ]] && echo "$out" && return
  for (( i=0; i<${#items}; i++ )) ; do
    ( perm "${items:0:i}${items:i+1}" "$out${items:i:1}" )
  done
  }
while read line ; do perm $line ; done < File

Since asker mentioned Perl is fine, I think Python 2.6+/3.X is fine, too:

由于提问者提到 Perl 很好,我认为 Python 2.6+/3.X 也很好:

python -c "from itertools import permutations as p ; print('\n'.join([''.join(item) for line in open('File') for item in p(line[:-1])]))"

For Python 2.5+/3.X:

对于 Python 2.5+/3.X:

#!/usr/bin/python2.5

# http://stackoverflow.com/questions/104420/how-to-generate-all-permutations-of-a-list-in-python/104436#104436
def all_perms(str):
    if len(str) <=1:
        yield str
    else:
        for perm in all_perms(str[1:]):
            for i in range(len(perm)+1):
                #nb str[0:1] works in both string and list contexts
                yield perm[:i] + str[0:1] + perm[i:]

print('\n'.join([''.join(item) for line in open('File') for item in all_perms(line[:-1])]))

On my computer using a bigger test file:

在我的计算机上使用更大的测试文件:

First Python code
  Python 2.6:     0.038s
  Python 3.1:     0.052s
Second Python code
  Python 2.5/2.6: 0.055s
  Python 3.1:     0.072s
awk:              0.332s
Bash (local):     2.058s
Bash (subshell): 22+s

回答by ghostdog74

A faster version using awk

使用 awk 的更快版本

function permute(s, st,     i, j, n, tmp) {
    n = split(s, item,//)
    if (st > n) {  print s; return }
    for (i=st; i<=n; i++) {
        if (i != st) {
         tmp = item[st]; item[st] = item[i]; item[i] = tmp
         nextstr = item[1]
         for (j=2; j<=n; j++) nextstr = nextstr delim item[j]
        }else {
          nextstr = s
        }
       permute(nextstr, st+1)
       n = split(s, item, //)
   }
}
{ permute(
$ awk -f permute.awk file
,1) }

usage:

用法:

while read a; do crunch 0 0 -p "$a"; done 2> /dev/null < File

回答by jyz

Using the crunchutil, and bash:

使用crunchutil 和bash

ab
ba
abc
acb
bac
bca
cab
cba

Output:

输出:

#!/bin/bash

list=`echo {0..9} {a..z} {A..Z}`

for c1 in $list
do
        for c2 in $list
        do  
                for c3 in $list
                do  
                         echo $c1$c2$c3
                done
        done
done

Tutorial here https://pentestlab.blog/2012/07/12/creating-wordlists-with-crunch/

教程在这里https://pentestlab.blog/2012/07/12/creating-wordlists-with-crunch/

回答by Brian Agnew

See the Perl Cookbookfor permutation examples. They're word/number oriented but a simple split()/join()on your above example will suffice.

有关排列示例,请参阅Perl Cookbook。它们是面向单词/数字的,但是上面示例中的简单split()/join()就足够了。

回答by gsbabil

Bash word-list/dictionary/permutation generator:

Bash 单词列表/字典/排列生成器:

The following Bash code generates 3 character permutation over 0-9, a-z, A-Z. It gives you (10+26+26)^3 = 238,328 words in output.

以下 Bash 代码在 0-9、az、AZ 上生成 3 个字符排列。它在输出中为您提供 (10+26+26)^3 = 238,328 个单词。

It's not very scalable as you can see you need to increase the number of forloop to increase characters in combination. It would be much faster to write such thing in assembly or C using recursion to increase speed. The Bash code is only for demonstration.

它的可扩展性不是很好,因为您可以看到您需要增加for循环次数以增加组合字符。在汇编或 C 中使用递归来提高速度会更快。Bash 代码仅用于演示。

P.S.You can populate $listvariable with list=$(cat input.txt)

PS您可以填充$list变量list=$(cat input.txt)

000
001
002
003
004
005
...
...
...
ZZU
ZZV
ZZW
ZZX
ZZY
ZZZ
[babil@quad[13:27:37][~]> wc -l t.out 
238328 t.out

SAMPLE OUTPUT:

样品输出:

$ ruby -ne '$_.chomp.chars.to_a.permutation{|x| puts x.join}' file # ver 1.9.1

回答by ghostdog74

while read s;do p="$(echo "$s"|sed -e 's/./&,/g' -e 's/,$//')";eval "printf "%s\\n" "$(eval 'echo "$(printf "{'"$p"'}%.0s" {0..'"$((${#s}-1))"'})"')"|grep '\(.\)*.*' -v";echo;done <f

回答by Michael Krupp

Because you can never have enogh cryptic Bash-oneliners:

因为你永远不可能有 enogh 神秘的 Bash-oneliners:

$ time while read s;do p="$(echo "$s"|sed -e 's/./&,/g' -e 's/,$//')";eval "printf "%s\\n" "$(eval 'echo "$(printf "{'"$p"'}%.0s" {0..'"$((${#s}-1))"'})"')"|grep '\(.\)*.*' -v";echo;done <f >/dev/null 

real 0m0.021s
user 0m0.000s
sys  0m0.004s

It's pretty fast - at least on my machine here:

它非常快 - 至少在我的机器上:

##代码##

But be aware that this one will eat a lot of memory when you go beyond 8 characters...

但是请注意,当您超过 8 个字符时,这个会占用大量内存......