배열의 보수를 찾으시나요?

배열의 보수를 찾으시나요?

다음에서이 문제, 파일에서 임의의 10줄을 추출하고 싶었고 이제 나머지 90줄을 별도의 파일로 원합니다.

문서에는 1부터 100까지의 인덱스가 있는 100개의 행이 있으므로 문제는 find 의 보수로 귀결 됩니다 ind.1, 2, ..., 100

ind=$(shuf -i 1-100 -n 10 | sort -n)

그래서 내 질문은

  1. 1, 2, ..., 100배열을 효율적으로 생성하는 방법은 무엇입니까 ? 그리고
  2. 완성하는데 사용할 수 있을 것 같습니다 comm. 그렇다면 comm파일 대신 배열을 어떻게 처리해야 합니까?

답변1

다른 스레드의 내 제안을 바탕으로:

awk '
  BEGIN { srand(); do a[int(100*rand()+1)]; while (length(a)<10) }
  NR in a
' ~/orig.txt > ~/short.txt

이를 변경하여 두 개의 파일을 만들 수 있습니다.

awk -v range=100 -v offset=1 -v amount=10 '
  BEGIN { srand(); do a[int(range*rand()+offset)]; while (length(a)<amount) }
  NR in a    { print > "short.txt" }
  !(NR in a) { print > "rest.txt" }
' ~/orig.txt

(이것은 내부적으로 awk사용할 수 없습니다 ~. 그러나 HOMEthrough는 ENVIRON[]다음과 같이 사용할 수 있습니다: print > ENVIRON["HOME"] "/short.txt"또는 resp., print > ENVIRON["HOME"] "/rest.txt".)

답변2

글쎄, 다시 생각해보니 - 난 일을 했어방법너무 어렵다. 필요한 것은 이것뿐입니다:

shuf -i 1-100 -n10 |
sed 's/$/{p;b\n}/' |
sed -nf - -e 'w separate_file' infile >outfile

n교체 대신 리터럴 개행 문자가 필요할 수도 있습니다 sed. 어쨌든, 이는 아래와 같은 일을 합니다. 다른 90줄을 모두 실행하는 데 방해가 되지 않습니다. 파일에 있기 때문에 제자리에 있을 뿐이므로 특별히 고려할 필요가 없습니다.

전체 거래는 다음과 같습니다.

set  " $(shuf -i 1-100 -n 10) "
while [ "$((i+=1))" -le 100 ]
do    [ -z "${1##*[!0-9]$i[!0-9]*}" ]
      printf "$i%.$((!$?))s%.$?s\n" p H 
done| sed -nf - -e '$!d;x;s/.//p' <infile >outfile

기본적으로 sed다음과 같은 스크립트를 작성합니다.

1H
2H
3H
4p
5H
...
90p
91H
...

그리고 100까지 계속됩니다. 마지막 줄에서 - 무작위로 선택된 모든 줄이 p인쇄 된 후 이전 공백 x으로 변경 하고 처음 삽입된 ewline 문자를 바꾸고 나머지를 인쇄합니다.Hs///\np

셸 루프 없이 이를 수행하려면 다음을 수행할 수 있습니다.

set  "$(shuf -i 1-100 -n 10)"
{ seq 100 | grep -Fxv "$1"; echo "$1"; } |
sed '1,90s/$/H/;91,$s/$/p/' |
sed -nf - -e '$!d;x;s/.//p' <infile >outfile

하지만 이 규모에서는 그것이 도움이 될지 확신할 수 없습니다.

아무튼 seq 100출력파일을 테스트삼아 실행해보고 출력해봤는데..

3
4
5
19
57
63
64
73
80
88
1
2
6
7
8
9
10
11
12
13
14
15
16
...

...초기 무작위 100에 포함되지 않은 모든 행에 대해 최대 100입니다.

답변3

bash를 사용하는 또 다른 솔루션은 다음과 같습니다. 먼저 ind 변수에서 배열을 생성할 수 있습니다.

ind=($(shuf -i 1-100 -n 10 | sort -n))

1..100 범위의 숫자를 포함하는 배열을 만들려면 간단한 방법은 다음과 같습니다.

numbers=({1..100})

보완을 얻으려면 uniq -u를 사용합니다. 이 명령은 정렬된 목록에서 모든 중복 항목을 정렬합니다. 마지막 붙여넣기 명령은 모든 값을 다시 한 줄에 넣습니다.

complement=($(echo ${ind[*]} ${numbers[*]} | sed 's/ /\n/g' | sort -n | uniq -u | paste -sd " " - ))
echo ${complement[*]}

질문을 다시 생각해 보면 이 모든 것은 bash 배열 없이도 수행될 수 있습니다.

ind=$(shuf -i 1-100 -n 10 | sort -n)
echo $ind {1..100} | sed 's/ /\n/g' | sort -n | uniq -u | paste -sd " " -

답변4

명령줄에서 모든 작업을 수행할 수 있다고 확신하지만 실제 프로그래밍 언어를 사용하면 일부 문제를 더 잘 해결할 수 있습니다. 예를 들어 문제에 대한 Python 기반 솔루션은 다음과 같습니다.

import random
import pprint

with open("file.txt", "w") as f:
  # create a file filled with numbers from 00 to 99
  f.writelines(map(lambda x: "%02d\n" % x, range(100)))

with open("file.txt") as f:
  # read it and assign each line to array, strip newlines 
  ar = set(map(lambda x: x.strip(), f.readlines()))

selection = set(random.sample(ar, 10))
rest = ar - selection

pprint.pprint(selection)
pprint.pprint(rest)

관련 정보