문자열의 단어를 뒤섞기

문자열의 단어를 뒤섞기

개행으로 구분된 문자열이 포함된 텍스트 파일이 있습니다. 내 문제는 각 줄을 다음과 같이 처리하는 것입니다. 공백을 구분 기호로 사용하여 토큰 순서를 섞습니다.

예를 들어:

입력하다: A B C

산출: C A B

물론 명령/스크립트를 반복적으로 실행하면 다른 순서가 제공되어야 합니다.

내 현재 솔루션(한 줄의 텍스트):

$ cat <file> | tr " " "\n" | shuf | tr "\n" " "

여러 줄의 텍스트 파일을 처리하기 위한 좋은(더 나은) 명령줄 조합이 있습니까?

답변1

POSIXly에서는 다음과 같이 이 작업을 상대적으로 효율적으로 수행할 수 있습니다(확실히 awk모든 입력 줄에 대해 하나 이상의 GNU 유틸리티를 실행하는 것보다 더 효율적).shuf

awk '
  BEGIN {srand()}
  {
    for (i = 1; i <= NF; i++) {
      r = int(rand() * NF) + 1
      x = $r; $r = $i; $i = x
    }
    print
  }' < your-file

(대부분의 awk구현에서 동일한 명령을 동일한 초 내에 두 번 실행하면 동일한 결과가 나올 수 있습니다. 사용되는 기본 무작위 시드는 srand()일반적으로 초 단위의 현재 에포크 시간을 기반으로 하기 때문입니다.)

답변2

원래 명령을 다음과 같이 단순화할 수 있습니다.

shuf -e A B C | tr "\n" " " && echo ""

또는

shuffled=( $(shuf -e A B C) ) ; echo ${shuffled[*]}

내 생각엔 이것이 기본 테스트보다 덜 번거롭고 더 빠르다고 생각합니다.

~/test포함된 파일이 있는 경우

A B C
D E F

다음을 사용하여 각 라인을 스크램블하고 에코할 수 있습니다.

while IFS= read -r line; do shuffled=( $(shuf -e $line) ) ; echo ${shuffled[*]} ; done < ~/test

또는 스크립트 형식으로:

#!/bin/bash
while IFS= read -r line
    do shuffled=( $(shuf -e $line) )
    echo ${shuffled[*]}
done < ~/test

스크립트에 인수를 전달할 ~/test위치 를 바꿀 수 있습니다 .$1

결과:

B C A
G E F

작동 원리:

shuf -e공백과 줄 바꿈으로 분할됩니다. 하지만 이는 ABC를 세 개의 인수로 처리하기 때문입니다.

따라서 shuf -e A B C AB와 C의 순서는 깨지게 되지만 shuf -e "A B C" AB와 C의 순서는 깨지지 않게 됩니다.

이를 사용하여 각 줄을 배열로 읽은 다음 를 사용하여 다시 인쇄할 수 있습니다 echo.

while IFS= read -r line;

$line각 행은 이 루프에 전달될 때 읽혀집니다 <.

do shuffled=( $(shuf -e $line) )

$shuffled리터럴 확장을 통해 shuf -e $line변수의 각 행에서 배열이 생성됩니다 shuf -e A B C.

echo ${shuffled[*]}

기본적으로 각 요소 사이에 공백을 넣어 인쇄하는 배열을 에코합니다.

< ~/test

~/test루프에 라인을 입력하십시오 .

답변3

주어진

$ cat file
A B C
D E F
G H I J

shuffle그런 다음 Perl의 List::Util 모듈을 사용하십시오 .

$ perl -MList::Util=shuffle -alpe '$_ = join " ", shuffle @F' file
C B A
E D F
I J G H

bash를 사용 read -a하고 shuf(그러나 한 줄에 3개의 유틸리티를 실행하고 그 중 2개는 내장되어 있지 않으므로 매우 비효율적입니다):

$ while read -ra arr; do shuf -e -- "${arr[@]}" | paste -sd ' ' -; done < file
A C B
F E D
J I G H

답변4

매개변수를 한 줄로 전달하려면:

shuf -e one two three four그게 당신이 필요한 전부입니다.

shuf -e $(cat <file>) | tr "\n" " "예제에 표시된 것처럼 한 줄만 있는 파일의 경우.

여러 줄의 경우:

while read line; do shuf -e $line | tr "\n" " " && echo \n; done < <file>

관련 정보