string.txt와 lengths.txt라는 두 개의 텍스트 파일이 있습니다.
String.txt :
abcdefghijklmnopqrstuvwxyz
lengths.txt
5
4
10
7
파일을 받고 싶습니다
>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz
약 28,000 개의 항목을 작업 중이며 200 ~ 56,000 자 사이에서 다양합니다.
현재 다음을 사용하고 있습니다.
start=1
end=0
i=0
while read read_l
do
let i=i+1
let end=end+read_l
echo -e ">Entry_$i" >>outfile.txt
echo "$(cut -c$start-$end String.txt)" >>outfile.txt
let start=start+read_l
echo $i
done <lengths.txt
그러나 매우 비효율적입니다. 더 좋은 아이디어가 있습니까?
답변
넌 할 수있어
{
while read l<&3; do
{
head -c"$l"
echo
} 3<&-
done 3<lengths.txt
} <String.txt
설명이 필요합니다.
주요 아이디어는 사용 { head ; } <file
하는 것이며 과소 평가 된 @mikeserv 답변 에서 파생됩니다 . 그러나이 경우 우리는 많은 head
s 를 사용해야 하므로 두 파일 (입력 할 파일 의 주요 파일과 옵션 의 인수로 줄)에서 입력 while
을 전달하기 위해 루프가 도입되고 파일 설명자와 약간 조정됩니다. . 아이디어는 속도가 좋아질 때 마다 명령을 받거나 호출 할 때마다 탐색 할 필요가 없다는 것입니다 . 는 각 반복 후 개행 문자를 인쇄 할 만하다.head
String.txt
length.txt
-c
String.txt
head
cut
echo
얼마나 빠르며 (있는 경우) >Entry_i
줄 사이에 추가 하는 것이 운동으로 남습니다.
답변
일반적으로 쉘 루프를 사용하여 text를 처리하고 싶지 않습니다 . 여기에 다음을 사용합니다 perl
.
$ perl -lpe 'read STDIN,$_,$_; print ">Entry_" . ++$n' lengths.txt < string.txt
>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz
그것은 하나의 명령입니다 (버퍼링으로 read
한 번에 1 바이트 (또는 일반 파일의 경우 몇 바이트)를 읽는 쉘 명령 보다 훨씬 효율적으로 버퍼링 ). 두 파일을 한 번만 (메모리에 완전히 저장하지 않고) 읽습니다. 쉘 루프에서 외부 명령을 실행하는 솔루션보다 몇 배 더 효율적입니다.
( -C
이 숫자가 바이트 수와 달리 현재 로케일의 문자 수 여야하는 경우 옵션을 추가하십시오 . 샘플과 같은 ASCII 문자의 경우 아무런 차이가 없습니다.)
답변
bash, 버전 4
mapfile -t lengths <lengths.txt
string=$(< String.txt)
i=0
n=0
for len in "${lengths[@]}"; do
echo ">Entry_$((++n))"
echo "${string:i:len}"
((i+=len))
done
산출
>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz
답변
무엇에 대해 awk
?
process.awk
이 코드로 불리는 파일을 만듭니다 :
function idx(i1, v1, i2, v2)
{
# numerical index comparison, ascending order
return (i1 - i2)
}
FNR==NR { a[FNR]=$0; next }
{ i=1;PROCINFO["sorted_in"] = "idx";
for (j in a) {
print ">Entry"j;
ms=substr($0, i,a[j])
print ms
i=i+length(ms)
}
}
저장하고 실행 awk -f process.awk lengths.txt string.txt