배쉬-파일의 각 라인을 페어링


10

이 질문은 강력하게 관련되어 질문입니다. 각 줄이 파일의 경로 인 여러 줄이 포함 된 파일이 있습니다. 이제 각 줄을 서로 다른 줄 과 짝을 이루고 싶습니다 (자체가 아님). 또한 쌍 A BB A내 목적을 위해 쌍 과 동일 하므로 이러한 조합 중 하나만 생성해야합니다.

files.dat 속기 표기법으로 이와 같이 읽 히면 각 문자는 파일 경로입니다 (절대 또는 상대)

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

바람직하게는 이것을 bash에서 해결하고 싶습니다. 다른 질문과 달리 내 파일 목록은 다소 작기 때문에 (약 200 줄) 루프와 RAM 용량을 사용하면 아무런 문제가 없습니다.


bash에 있어야합니까 , 아니면 bash 명령 줄을 통해 사용할 수 있습니까? 다른 유틸리티는 텍스트를 처리하는 것이 좋습니다.
Jeff Schaller

@JeffSchaller bash 명령 줄을 통해 접근 할 수있는 것. 조금 불분명해서 죄송합니다
Enno

이것은 거의 코드 골프 가되고있다 : P
Richard de Wit

3
일반적으로 사소한 작업을 수행해야하는 한 BASH에서 선호하는 스크립팅 언어를 사용하십시오. 취약성 (예 : 특수 문자 나 공백)이 적고 필요할 때마다 확장하기가 훨씬 쉽습니다 (3 개가 필요하거나 일부를 필터링 한 경우). Python 또는 Perl은 거의 모든 Linux 상자에 설치해야하므로 Busybox와 같은 임베디드 시스템에서 작업하지 않는 한 좋은 선택입니다.
Davidmh

답변:


7

이 명령을 사용하십시오 :

awk '{ name[$1]++ }
    END { PROCINFO["sorted_in"] = "@ind_str_asc"
        for (v1 in name) for (v2 in name) if (v1 < v2) print v1, v2 }
        ' files.dat

PROCINFOgawk확장 일 수 있습니다 . 당신 awk이 그것을 지원하지 않는 경우 , PROCINFO["sorted_in"] = "@ind_str_asc"라인을 떠나서 출력을 파이프하십시오 sort(출력을 정렬하려면).

(이는 입력을 정렬 할 필요 가 없습니다 .)


8
$ join -j 2 -o 1.1,2.1 file file | awk '!seen[$1,$2]++ && !seen[$2,$1]++'
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e

입력 파일에 공백이없는 줄이 있다고 가정합니다. 또한 파일 이 정렬되어 있다고 가정합니다 .

join명령은 파일에서 행의 전체 교차 곱을 작성합니다. 존재하지 않는 필드에서 파일 자체와 결합하여이를 수행합니다. 비표준 -j 2-1 2 -2 2( 대신 -j2GNU를 사용하지 않는 한) 대체 될 수 있습니다 join.

awk명령이 결과를 판독 만 아직 보이지 않았다 쌍 높은 결과를 출력한다.


"파일이 정렬되었습니다"는 무슨 뜻입니까? 어떤 기준으로 정렬 했습니까?
Enno

@ Enno 정렬 방법 sort -b을 정렬했습니다. join정렬 된 입력 파일이 필요합니다.
Kusalananda

8

python솔루션입니다. 입력 파일은 itertools.combinations표준 라이브러리에서 제공되며 형식이 지정되고 표준 출력으로 인쇄되는 2 길이 튜플을 생성합니다.

python3 -c 'from itertools import combinations
with open("file") as f:
    lines = (line.rstrip() for line in f)
    lines = ("{} {}".format(x, y) for x, y in combinations(lines, 2))
    print(*lines, sep="\n")
'

6

당신이 만약 ruby설치 :

$ ruby -0777 -F'\n' -lane '$F.combination(2) { |c| puts c.join(" ")}' ip.txt
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
  • -0777 전체 파일을 훑어보기 (파일 크기가 작다는 OP에서 언급했듯이 괜찮을 것입니다)
  • -F'\n'줄 바꿈을 기준으로 분할되므로 각 줄은 $F배열 의 요소가 됩니다.
  • $F.combination(2)2한 번에 조합 요소 생성
  • { |c| puts c.join(" ")} 필요에 따라 인쇄
  • 입력 파일에 중복이 포함될 수있는 경우 $F.uniq.combination(2)


한 번에 3 가지 요소 :

$ ruby -0777 -F'\n' -lane '$F.combination(3) { |c| puts c.join(" ")}' ip.txt
a b c
a b d
a b e
a c d
a c e
a d e
b c d
b c e
b d e
c d e


포함 perl(일반 아님)

$ perl -0777 -F'\n' -lane 'for $i (0..$#F) {
                             for $j ($i+1..$#F) { 
                               print "$F[$i] $F[$j]\n" } }' ip.txt
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e


awk

$ awk '{ a[NR]=$0 }
       END{ for(i=1;i<=NR;i++)
              for(j=i+1;j<=NR;j++)
                print a[i], a[j] }' ip.txt 
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e

5

순수한 껍질에 하나 있습니다.

test $# -gt 1 || exit
a=$1
shift
for f in "$@"
do
  echo $a $f
done
exec /bin/sh $0 "$@"

예:

~ (137) $ sh test.sh $(cat file.dat)
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
~ (138) $ 

1
명령 대체는 후행 줄 바꿈을 제거하므로 다음과 같은 방법을 사용하는 것이 <file.dat xargs test.sh좋습니다.test.sh $(cat file.dat)
iruvar

1

사용 Perl과 같이 우리가 그것을 할 수 있습니다 :

$ perl -lne '
     push @A, $_}{
     while ( @A ) {
        my $e = shift @A;
        print "$e $_" for @A;
     }
' input.txt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.