bash - 다른 파일에서 가능한 모든 단어 조합

bash - 다른 파일에서 가능한 모든 단어 조합

나는 가지고있다N파일당 한 단어씩

파일 1 파일 2 파일 3...
1_a 2_a 3_a
1_b 2_b 3_b
1_c 3_c

나는 이 모든 파일을 가져와 n 단어(각 파일당 하나씩)의 가능한 모든 조합을 생성하는 bash 스크립트를 작성하고 싶습니다.

내 예에서는 다음 결과를 원합니다.

1_a 2_a 3_a
1_a 2_a 3_b
1_a 2_a 3_c
1_a 2_b 3_a
1_a 2_b 3_b
1_a 2_b 3_c
1_b 2_a 3_a
1_b 2_a 3_b
1_b 2_a 3_c
1_b 2_b 3_a
1_b 2_b 3_b
1_b 2_b 3_c
1_c 2_a 3_a
1_c 2_a 3_b
1_c 2_a 3_c
1_c 2_b 3_a
1_c 2_b 3_b
1_c 2_b 3_c

Paste와 awk로 이 작업을 시도했지만 실패했습니다. 어떻게 해야 하나요?

답변1

처리할 파일이 있을 때 재귀 함수를 사용하여 자신을 호출할 수 있습니다.

#!/bin/bash

process () {
    local prefix=$1
    local file=$2
    shift 2
    while read line ; do
        if (($#)) ; then                  # There are still unprocessed files.
            process "$prefix $line" "$@"
        else                              # Reading the last file.
            printf '%s\n' "$prefix $line"
        fi
    done < "$file"
}

process '' "$@"

답변2

parallel --line-buffer --keep-order echo :::: file1 :::: file2 :::: file3

https://www.gnu.org/software/parallel/parallel_tutorial.html#multiple-input-sources

답변3

당신이 그런 말을 한 건 알아요 bash. 하지만 이것은 다음과 같은 것에 딱 맞습니다.python 3.3+

import sys
from contextlib import ExitStack
from itertools import product

with ExitStack() as stack:
  files = [stack.enter_context(open(f)) for f in sys.argv[1:]]
  for x in product(*files):
    x = [y.rstrip('\n') for y in x]
    print(*x)

위의 코드를 이라는 파일에 넣고 combo.py호출하면 python combo.py file_1 file_2 file_3 생성됩니다 .

1_a 2_a 3_a
1_a 2_a 3_b
1_a 2_a 3_c
1_a 2_b 3_a
1_a 2_b 3_b
1_a 2_b 3_c
1_b 2_a 3_a
1_b 2_a 3_b
1_b 2_a 3_c
1_b 2_b 3_a
1_b 2_b 3_b
1_b 2_b 3_c
1_c 2_a 3_a
1_c 2_a 3_b
1_c 2_a 3_c
1_c 2_b 3_a
1_c 2_b 3_b
1_c 2_b 3_c

답변4

Bash의 Brace 확장은 작업에 적합한 도구를 제공합니다. 다음과 같은 간단한 경우를 생각해 보십시오.

$ echo {1..3}{a..c}
1a 1b 1c 2a 2b 2c 3a 3b 3c

귀하의 예에서는 다음과 같은 내용이 있습니다.

$ echo {1_a,1_b,1_c}{2_a,2_b}{3_a,3_b,3_c}
1_a2_a3_a 1_a2_a3_b 1_a2_a3_c 1_a2_b3_a 1_a2_b3_b 1_a2_b3_c 1_b2_a3_a 1_b2_a3_b 1_b2_a3_c 1_b2_b3_a 1_b2_b3_b 1_b2_b3_c 1_c2_a3_a 1_c2_a3_b 1_c2_a3_c 1_c2_b3_a 1_c2_b3_b 1_c2_b3_c

맞는 말이지만 읽기가 어렵습니다. 더 잘 설명하기 위해 생성된 출력을 배열에 넣은 다음 배열을 인쇄할 수 있습니다.

$ combos=({1_a,1_b,1_c}{2_a,2_b}{3_a,3_b,3_c})
$ for i in "${combos[@]}"; do echo "$i"; done
1_a2_a3_a
1_a2_a3_b
1_a2_a3_c
1_a2_b3_a
1_a2_b3_b
1_a2_b3_c
1_b2_a3_a
1_b2_a3_b
1_b2_a3_c
1_b2_b3_a
1_b2_b3_b
1_b2_b3_c
1_c2_a3_a
1_c2_a3_b
1_c2_a3_c
1_c2_b3_a
1_c2_b3_b
1_c2_b3_c

결합된 각 요소 사이에 간격을 추가하여 다음과 같이 보이게 만드는 방법에는 여러 가지가 있습니다.

1_a 2_a 3_a
..
..

그러나 그것은 별도로 물어볼 수 있는 또 다른 질문입니다.

관련 정보