繁体   English   中英

有没有办法在 linux bash 的 for 循环中对文件名进行排列?

[英]Is there a way to make permutations for file names in a for loop in linux bash?

这个想法是您有 3 个文本文件,我们将其命名为A B C ,其中您只有一个带有字符串的唯一列(本示例中的内容无关紧要)。 您想要的是在这三个之间建立一个连接 function,因此您将连接A - B另一个连接B - C和最后一个连接 A - Z0D61F8370CAD1D412F570B84D143 ,如果它是一个排列。

让我们做一个图形示例。 个人代码将是

join -1 1 -2 1 A.txt B.txt > AB.txt

其他 2 以此类推

想象A

100
101
102
104

101
103
104
105

C

100
103
104
105

所以A - B比较( AB.txt )将是:

101
104

A - C比较( AC.txt ):

100
104

B - C比较( BC.txt ):

103
105

您将拥有三个 output 文件,以比较AB.txtAC.txtBC.txt 命名

解决方案可能如下所示:

#!/usr/bin/env bash

# Read positional parameters into array
list=("$@")

# Loop over all but the last element
for ((i = 0; i < ${#list[@]} - 1; ++i)); do
    # Loop over the elements starting with the first after the one i points to
    for ((j = i + 1; j < ${#list[@]}; ++j)); do
        # Run the join command and redirect to constructed filename
        join "${list[i]}" "${list[j]}" > "${list[i]%.txt}${list[j]%.txt}".txt
    done
done

请注意, -1 1 -2 1join的默认行为,可以跳过。

必须使用文件名作为参数调用脚本:

./script A.txt B.txt C.txt

我会将文件放在一个数组中,并使用如下索引:

files=(a.txt b.txt c.txt) # or files=(*.txt)

for ((i=0; i<${#files[@]}; i++)); do
    f1=${files[i]} f2=${files[i+1]:-$files}
    join -1 1 -2 1 "$f1" "$f2" > "${f1%.txt}${f2%.txt}.txt"
done

使用echo join进行调试(并引用> ),这就是将要执行的:

join -1 1 -2 1 a.txt b.txt > ab.txt
join -1 1 -2 1 b.txt c.txt > bc.txt
join -1 1 -2 1 c.txt a.txt > ca.txt

或者对于六个文件:

join -1 1 -2 1 a.txt b.txt > ab.txt
join -1 1 -2 1 b.txt c.txt > bc.txt
join -1 1 -2 1 c.txt d.txt > cd.txt
join -1 1 -2 1 d.txt e.txt > de.txt
join -1 1 -2 1 e.txt f.txt > ef.txt
join -1 1 -2 1 f.txt a.txt > fa.txt

LC_ALL=C; files(*.txt) LC_ALL=C; files(*.txt)将使用当前目录中的所有.txt文件,按名称排序,这可能是相关的。

GNU awk 中的一个:

$ gawk '{
    a[ARGIND][$0]                          # hash all files to arrays
}
END {                                      # after hashing
    for(i in a)                            # form pairs
        for(j in a)
            if(i<j) {                      # avoid self and duplicate comparisons
                f=ARGV[i] ARGV[j] ".txt"   # form output filename
                print ARGV[i],ARGV[j] > f  # output pair info
                for(k in a[i])     
                    if(k in a[j])
                        print k > f        # output matching records
            }
}' a b c

Output,例如:

$ cat ab.txt
a b
101
104

所有文件都在开头的 memory 中进行哈希处理,因此如果文件很大,您可能会用完 memory。

一个 function 除了在其 arguments 中生成两个可能的组合之外什么都不做:

#!/bin/bash

combpairs() {
    local a b
    until [ $# -lt 2 ]; do
        a="$1"
        for b in "${@:2}"; do
            echo "$a - $b"
        done
        shift
    done
}
combpairs A B C D E
A - B
A - C
A - D
A - E
B - C
B - D
B - E
C - D
C - E
D - E

另一种变化

declare -A seen
for a in {A,B,C}; do 
    for b in {A,B,C}; do
        [[ $a == $b || -v seen[$a$b] || -v seen[$b$a] ]] && continue
        seen[$a$b]=1
        comm -12 "$a.txt" "$b.txt" > "$a$b.txt"
    done
done

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM