답변:
당신은 필요하지 않습니다 input-duplicated.txt
.
시험:
mycommand <(perl -0777pe '$_=$_ x 1000' input-data.txt)
0777
: -0
입력 레코드 구분 기호를 설정합니다 ( $/
기본적으로 줄 바꿈 인 perl 특수 변수 ). 이 값을 더 큰 값으로 설정 0400
하면 Perl이 전체 입력 파일을 메모리에 넣습니다.pe
: -p
"각 스크립트를 적용한 후 각 입력 행을 인쇄합니다" 라는 의미 -e
입니다.$_=$_ x 1000
: $_
는 현재 입력 라인입니다. 로 인해 전체 파일을 한 번에 읽고 있기 때문에 전체 파일을 -0700
의미합니다. 는 x 1000
전체 파일의 1,000 카피 인쇄 당할 것이다.perl
매우 효율적이며이를 위해 설계되었습니다.
원래 보조 파일을 생성해야한다고 생각했지만 Bash에서 원본 파일을 반복하고 리디렉션을 사용하여 파일로 표시 할 수 있습니다.
루프를 수행하는 방법에는 12 가지가 있지만 여기에는 4 가지가 있습니다.
mycommand <( seq 1000 | xargs -i -- cat input-data.txt )
mycommand <( for _ in {1..1000}; do cat input-data.txt; done )
mycommand <((for _ in {1..1000}; do echo input-data.txt; done) | xargs cat )
mycommand <(awk '{for(i=0; i<1000; i++)print}' input-data.txt) #*
세 번째 방법은 아래의 maru의 의견에서 즉흥적으로 이루어졌으며 cat에 대한 입력 파일 이름의 큰 목록을 작성합니다. xargs
이것을 시스템이 허용하는 한 많은 인수로 나눕니다. 그것은이다 훨씬 보다 빠른 n은 별도의 고양이.
awk
(영감 방법 terdon의 대답은 ) 아마도 가장 최적화 된이지만 한 번에 각 라인을 복제합니다. 이것은 특정 응용 프로그램에 적합하거나 적합하지 않을 수 있지만 번개처럼 빠르고 효율적입니다.
그러나 이것은 즉시 생성됩니다. Bash 출력은 읽을 수있는 것보다 훨씬 느리므로 테스트를 위해 새 파일을 생성해야합니다. 고맙게도 그것은 매우 간단한 확장 일뿐입니다.
(for _ in {1..1000}; do echo input-data.txt; done) | xargs cat > input-duplicated.txt
mycommand input-duplicated.txt
cat $(for i in {1..N}; do echo filename; done)
. 이것은 arg 크기의 한계가 있지만 더 빠릅니다.
여기는 awk
해결책은 .
awk '{a[NR]=$0}END{for (i=0; i<1000; i++){for(k in a){print a[k]}}}' file
본질적으로 @Gnuc의 Perl만큼 빠릅니다 (1000 번 실행하고 평균 시간을 얻었습니다).
$ for i in {1..1000}; do
(time awk '{a[NR]=$0}END{for (i=0;i<1000;i++){for(k in a){print a[k]}}}' file > a) 2>&1 |
grep -oP 'real.*?m\K[\d\.]+'; done | awk '{k+=$1}END{print k/1000}';
0.00426
$ for i in {1..1000}; do
(time perl -0777pe '$_=$_ x 1000' file > a ) 2>&1 |
grep -oP 'real.*?m\K[\d\.]+'; done | awk '{k+=$1}END{print k/1000}';
0.004076
awk '{for(i=0; i<1000; i++)print}' input-data.txt
하여 한 번에 각 줄의 1000 사본 만 발행 할 수 있습니다. 모든 경우에 적합하지는 않지만 더 빠르고 지연이 적으며 전체 파일을 RAM에 저장할 필요가 없습니다.
123123123
괜찮다고하지만 111222333
아니었다. 귀하의 버전은 Gnouc보다 분명히 빠르며 평균 0.00297 초입니다. 편집 : 흠집, 실수했습니다. 실제로 0.004013 초에 해당합니다.
그냥 텍스트 편집기를 사용합니다.
vi input-data.txt
gg (move cursor to the beginning of the file)
yG (yank til the end of the file)
G (move the cursor to the last line of the file)
999p (paste the yanked text 999 times)
:wq (save the file and exit)
명령 행을 통해이를 수행해야하는 경우 (명령 이 없어서 vim
설치 vi
해야 함 :normal
) 다음을 사용할 수 있습니다.
vim -es -u NONE "+normal ggyGG999p" +wq input-data.txt
여기에서 -es
(또는 -e -s
) vim이 자동으로 작동하므로 터미널 창을 인계해서는 안되며 -u NONE
vimrc를 보지 않아야합니다. 많은 vim 플러그인).
다음은 간단한 한 줄짜리 스크립트입니다.
mycommand <(cat `yes input-data.txt | head -1000 | paste -s`)
`yes input-data.txt | head -1000 | paste -s`
텍스트를 생성 input-data.txt
공백으로 구분 된 1000 번cat
파일 목록으로 전달됩니다.xargs paste -s
합니까? 이것은 작동하지만 입력 파일에서 줄 바꿈을 유지하지 않습니다.
완전히 다른 스크립트로 작업하는 동안 2,900 만 줄의 텍스트를 사용하면 seek()
바이트 단위로 데이터를 사용 하고 조작하는 것이 종종 줄 단위보다 빠릅니다. 동일한 스크립트가 아래 스크립트에 적용됩니다. 파일을 열고 파일 열기 및 닫기를 반복하는 대신 (중요하지 않더라도 오버 헤드를 추가 할 수 있음) 파일을 열어 둔 채 처음으로 돌아갑니다.
#!/usr/bin/env python3
from __future__ import print_function
import sys,os
def error_out(string):
sys.stderr.write(string+"\n")
sys.exit(1)
def read_bytewise(fp):
data = fp.read(1024)
print(data.decode(),end="",flush=True)
while data:
data = fp.read(1024)
print(data.decode(),end="",flush=True)
#fp.seek(0,1)
def main():
howmany = int(sys.argv[1]) + 1
if not os.path.isfile(sys.argv[2]):
error_out("Needs a valid file")
fp = open(sys.argv[2],'rb')
for i in range(1,howmany):
#print(i)
fp.seek(0)
read_bytewise(fp)
fp.close()
if __name__ == '__main__': main()
스크립트 자체는 사용법이 매우 간단합니다.
./repeat_text.py <INT> <TEXT.txt>
3 줄의 텍스트 파일과 1000 회 반복의 경우 약 0.1 초가 적당합니다.
$ /usr/bin/time ./repeat_text.py 1000 input.txt > /dev/null
0.10user 0.00system 0:00.23elapsed 45%CPU (0avgtext+0avgdata 9172maxresident)k
0inputs+0outputs (0major+1033minor)pagefaults 0swaps
스크립트 자체는 가장 우아하지는 않지만 단축 될 수는 있지만 작업을 수행합니다. 물론 필자는 error_out()
기능 과 같은 몇 가지 추가 비트를 여기저기서 추가했다 . 이는 사용자에게 친숙한 작은 터치 일 뿐이다.
추가 파일이나 특수 프로그램, 순수한 배쉬 (이것은 고양이가 표준 명령입니다) 없이이 문제를 해결할 수 있습니다.
bash 내부의 printf 기능에 따라 반복되는 문자열을 생성 할 수 있습니다)
printf "test.file.txt %.0s\n" {1..1000}
그런 다음 1000 개의 파일 이름 목록을 반복하고 cat을 호출 할 수 있습니다.
printf "test.file.txt %.0s" {1..1000} | xargs cat
마지막으로, 우리는 출력을 명령에 출력하여 실행할 수 있습니다 :
mycommand "$( printf "%.0sinput.txt\n" {1..1000} | xargs cat )"
또는 명령이 stdin에서 입력을 받아야하는 경우 :
mycommand < <( printf "%.0sinput.txt\n" {1..1000} | xargs cat )
예, 이중 <가 필요합니다.